Monday, February 12, 2018

Groovy: Related Languages

The Groovy language is most directly related to Java. One key design consideration for Groovy was building it to integrate directly with the Java Runtime. In fact, any valid Java code is valid Groovy code. A Groovy application can also access the Java class library and third-party libraries. Even where the languages differ, the language implements these differences in a compatible way. An example is the cross compiling of a Groovy script into a Java class.
Groovy as a language does pull from other languages, however. These language elements include:
  • Ruby
    • Meta programming construct where a meta object is created for key objects providing runtime extension and introspection capabilities beyond what Java offers natively
    • Range type as demonstrated in the select/case statement
  • Python
    • list/map literal notation
    • syntax for default parameters
  • Smalltalk
    • collection processing methods
    • collect and inject naming scheme
  • Functional programming
    • Closures came from the world of functional programming (function pointers)

Groovy: Conclusions

Groovy is an interesting hybrid language that bridges the words of strictly-typed, object-oriented languages and dynamically-typed scripting languages.  Because it is built directly onto the JVM, it must adhere to the constructs of an object-oriented language.  However, despite this requirement, the language itself has built into it a number of abstractions that allow for the developer to utilize it as if it were a dynamically typed language.
These abstractions offer a level of power to the language that may not exist in Java itself.  These abstractions and extension include the ability to create domain specific languages and writing more compact and concise code.  It also makes learning the language easier for native Java developers than moving to Ruby or Python.
However, since these elements are grafted onto an underlying language, that can cause problems.   Following the Law of Leaky Abstractions, as coined by Joel Spolsky, there are places where a Groovy developer can encounter errors that may not make sense as they are covered by these abstractions.
class LeakyAbstraction
{
    int makeMeFail()
    {
         Random r = new Random()
         if(r.nextBoolean())
              return -1
 
         // Here’s a “hidden” type conversion error
        
    }
}
In the above example, the method makeMeFail is typed to return a primitive int.  In the case where nextBoolean returns true, this function will complete successfully as the return is a primitive integer.  However, if nextBoolean returns false, the return attempted is a NULL as Groovy will attempt to return the value of the last executed operation.  Because NULL cannot be converted to a primitive this causes a conversion exception.  This error may not make immediate sense to the developer as other scripting languages handle this more gracefully.
With that exception, the Groovy language does provide a welcome addition to the Java eco-system by providing an alternative to the strict, structured world of Java but still offering access to the full breadth of the Java ecosystem.

Groovy: Comparison to Programming Paradigms

Groovy is derived from Java and as such follows many of the object-oriented design paradigms, however its scripting nature and other elements allows it to implement elements of other programming paradigms.  This section compares Groovy to each of the key paradigms.

Imperative Programming

Unlike Java where everything is an object (with the exception of primitives), Groovy offers a scripting framework that allows for a more imperative method of programming.  A Groovy script operates as a set of variables containing data that can be acted upon via functions.  These functions perform operations and can return a result.  This result is stored can be stored in a variable in the code.
Unlike a true imperative language, like C, Groovy still maintains two key elements of object-oriented programming:
  • Unlike C, a variable in Groovy can store not only a value but also a reference to an object.
  • Under the covers, Groovy converts all scripts to a Java object in order to be executed by the JVM.  This conversion is transparent to the developer, but it is an abstraction that is described in greater detail in the next section.

Object-Oriented Paradigm

Groovy is an object-oriented language and follows all key OO paradigms including:
  • Everything is an object
  • Classes and subclasses for polymorphism
  • Inheritance
  • Inclusion polymorphism
As noted in the imperative paradigm section, Groovy does offer a scripting semantic that appears to implement the imperative paradigm.  However, at compilation time, the script itself is converted into a proper Java object with the globals, functions and other elements handled within the class.  Below is a sample Groovy script:
// A sample Groovy script
a = 1
def b = 2
 
def doSomething()
{
    def c = "Foo"
    def d = a
}
The following code example is the same script cross-compiled into Java by the Intelli-J integrated development environment.
// A cross compiled Groovy script
public class Sample extends Script {
    // Groovy-specific constructors omitted
    public static void main(String[] args) {
        new Sample(new Binding(args)).run();
    }
    public Object run() {
        setProperty("a", 1);
        Integer b = 1;
        return null;
    }
    public void doSomething() {
        String c = "Foo";
        Object d = this.getBinding().getProperty("a");
    }
}
Global variables are managed through a Bindings object which manages the scope and access within created methods.  Any functions created in the script are promoted to class-level methods.  All other elements are managed using normal object-oriented paradigms.

Concurrent Paradigm

Groovy implements elements of current programming.  The underlying processing model allows for:
  • Creating and managing multiple threads to process in a parallel or interleaved fashion
  • Event management
  • Mutual exclusion via synchronization and atomic object classes
  • Admission control via Semaphore

Functional Programming

Groovy implements elements of the functional programming paradigm through the implementation of closures.  Closures allow for defining a function as a variable and then using that function in various ways, including list processing.

Scripting

Groovy implements key elements of the scripting paradigm.  In fact, one of the primary goals when Groovy was created was to offer a scripting language like Python that targeted the Java Virtual Machine.  A developer can create a compact script of commands and variables that can be executed in an interactive fashion either via the groovy command line tool or in the Groovy shell.
It implements script-like variable binding and scope by offering script-level globals and variable definition within the script itself.  Variables are optionally typed, adding a def keyword that defines a variable as untyped.  Groovy offers the ability to scope variables and functions within packages and offers access to the underlying Java packaging system.
Data abstraction is accomplished using packages as well as through Java classes and objects.

Groovy: Language Evolution and Usage

After the initial release, the Groovy language continued to evolve and progress. Below are key features with each major release, not including pending releases.

Groovy 1.5

  • Added support for key conventions added in Java 1.5, including
    • Annotations - syntactic metadata added to classes and methods for use by the compiler and at runtime.
    • Enumerations (enum) - named lists of pre-defined constants
    • Static Imports - importing static methods from other classes into a class o Generics
    • Classical for loop
  • Domain Specific Language - the ability to extend the language with domain specific naming, allowing programmers to work with language and structures that are specific to their domain and have them mapped to the appropriate Groovy code
  • Elvis Operator - a simple conditional of <test> ? <ifTrue> : <ifFalse>

Groovy 2.0

  • Static type checking - while Groovy is an optionally typed language, version 2.0 added the ability to indicate that static type checking is required for a class
  • Static compilation - added the ability to compile objects as native Java classes rather than using the meta object protocol
  • Implemented additional Java 1.7 features
    • Binary literals
    • Underscore literals
    • Multi-catch blocks
  • Extension Modules
  • Contributing instance and static methods (similar to adding to a JS prototype) 

Groovy 2.1

  • Compile time meta-annotations
  • The GPars 1.0 concurrency and threading library was included
  • Definable custom base classes, allowing a programmer to select which base class to extend for a Groovy object rather than the language defined one

Groovy 2.2

  • Better interaction with Java 8 lambdas

Groovy 2.3

  • Official JDK 8 support
  • Traits
  • Template markup engine - a mechanism for formatting text output

Groovy 2.4 (current)

  • Support for writing Android apps in Groovy
  • Other enhancements

Usage

While the Groovy language was not targeted at a specific industry or vertical sector of the programming language market, like ADA for example, it has been embraced in web development circles, including the Grails web application development framework.  It also provides the core language for Samsung’s SmartThings home automation platform.

Groovy: Advanced Concepts: Concurrency

Groovy supports multithreaded operation, deriving its capabilities from the Java language itself.  This includes thread-based processing and concurrent processing capabilities.
In order to implement concurrency, Groovy operates on a single-process, multi-threading model.  Each process contains at least one thread and it has the ability to create multiple additional threads, each capable of performing separate work.  These threads share access to the same data, so the language implements a set of critical region and semaphore capabilities to allow for protecting access and updates to shared memory.

Control and Creation

The core language object in Java, and by extension Groovy, for managing multi-threading are java.lang.Thread and java.lang.Runnable.  The Thread object represents a single thread of execution within a Java process.  The language allows a developer to create, monitor and affect the processing of a given thread.
In order to create a thread, a class must be created that implements the Runnable interface.  This interface offers a single run method that is the developer will implement and provide the main entry point for the thread to start execution.  The developer will first create an instance of the class, then create the Thread object using the new class and finally calling the Thread.start() method to being processing.
Threads in Groovy are interruptible and include a set of exceptions that can be thrown if a sleeping or blocked thread is interrupted.  They also offer a wait for operation called join that allows a parent thread to wait for the completion of the thread processing before continuing.
class Worker implements Runnable
{
    public void run()
    {
         // Work goes here
    }
}
 
class Parent
{
    static void main(String[] args)
    {
         // Create the worker object
         Worker w = new Worker();
         // Create the new thread
         Thread t = new Thread(w);
         // Start the thread
         t.start();
         // Wait for the thread to complete processing
         t.join();
    }
}

Critical Regions and Semaphores

When it is necessary to make execution a section of code mutually exclusive, Groovy offers the ability to surround that code in a lock block.  Locks apply to a specific object and when a second thread attempts to access the same block as another thread, it will wait until the lock has been released.
One of the simplest methods for managing access is by marking a method as synchronized or by the synchronized(this) {} semantic.  This locks access to the entire object, giving mutually exclusive access to the object and its memory structures to the requesting thread.  All other threads are placed in wait until that section has completed processing.
public class Example
{
    synchronized void mutexMethod()
    {
         // Only one thread can execute this code
         // at a time
    }
 
    void method()
    {
         synchronized(this)
         {
              // This code block is mutex
         }
    }
}
The synchronized block semantic described above does not apply only to the object it is defined in, it can also apply to any other objects available within the execution scope.
In addition to the synchronized mutex described above, Groovy also offers a Semaphore class which allows for limiting access to a set of code and resources not to a single thread alone, but to a pre-defined number of threads.  It follows the baseline pattern of initialize/wait/signal.  Creating a Semaphore object defines the number of permits, the acquire methods implements wait and signal and the release methods implement the relinquish.
Groovy also implements a number of atomic objects that manage mutex access to primitive values, such as integer or floating point, and offer synchronized methods to get and increment the value of that object.

Events

Groovy implements events via the base Object’s wait and notify methods.  A given thread can call the wait method which will place that thread in a wait state until the corresponding signal is received.  This signal is set by the Object’s notify method.
// Wait code in one thread
synchronized(obj)
{
    obj.wait()
}
 
// Send signal code in separate object
synchronized(obj)
{
     obj.notify()
}

Groovy: Advanced Concepts: Sequencers

In addition to the sequencers and control flow elements described in Control Flow, Groovy also implements the following additional sequencers: jumps, escapes and exceptions.

Jumps

Java implements limited jump capabilities, limited to the break and continue escapes, as described in the next section.

Escapes

The Groovy language supports the following escape and branching statements: break, continue and return.  Each of these allow for escaping or modifying the next step in a loop or function.

break

Within a loop or switch, a break instructs the runtime to exit that composite statement.  This is useful when a loop needs to be terminated without meeting its completion criteria or when a particular case statement is complete.
while(true)
{
    // Break when the first true is returned
    if(new Random().nextBoolean())
        break;
}
 
switch(1)
{
    case 1:
        // Do something and then exit
        break;
    case 2:
    case 3:
        // Case 2 falls through to case 3
    default:
        // Case 2 and 3 will fall through
}
Breaks can be both labeled and unlabeled, implementing a limited form of jump.  Unlabeled break statements will terminate the innermost statement, while a labeled break statement will break labeled statement. [10]  The following example will break the outermost for loop when i is greater than 5 and when i + j equals 17.
outermost:
for(int i = 0; i < 10; i++)
{
    for(int j = 0; j < 10; j++)
    {
        if(i < 5 && i + j == 17)
            break;
   
        if(i + j == 17)
            break outermost
           
        println "${i},${j} = ${i+j}"
    }
}

continue

Within a loop, a continue statement will cause the processing of loop commands to stop and control be returned to the top of the loop.  The following example will only print the odd numbers as even numbers will satisfy the if statement, triggering the continue.
for(int i = 0; i < 10; i++)
{
    if(i % 2 == 0)
        continue;
       
    println i
}
In the same way as break statements, continue statements can be labeled or unlabeled.  Continues will follow the same rules for which loop to target if labeled or unlabeled.

return

The final flow control statement supported by Groovy is the return statement.  Within a function or method, a return statement will immediately exit the function and, if provided, return the value defined in the return statement.  The value returned must be of a compatible type to the defined return value for the function.
Groovy adds an additional consideration in that, unlike Java, Groovy will assume the output of the last operation will be returned at the end of a function.  If the final statement does not return a value, Groovy will attempt to return a value of null.  This can result in class cast exceptions if care is not taken to ensure all function exit points return the appropriate data type because the compiler may not catch these edge cases.

Exceptions

Groovy offers exception handling like that of Java.  In the instance of a programming error, unintended condition or other unrecoverable error, a method or operation can throw an exception.  This exception is an object that is ultimately a subclass of java.lang.Exception.  This object includes the ability to include a descriptive message and the initial cause of the exception.
Groovy exceptions are implemented by wrapping a function call, or set of function calls, in a try block.  The try block is followed by one or more catch blocks.  Each catch block defines one or more exception classes and a collection of statements to be executed in the event of an exception of that type.  A try/catch block is optionally followed by a finally block.  The code in the finally block is executed regardless of whether an exception is thrown or not and is often used to clean up resources.
try
{
}
catch(ExceptionTypeOne e1)
{
    // code do deal with ExceptionTypeOne and any subclasses
}
catch(ExceptionTypeTwo e2)
{
    // code do deal with ExceptionTypeTwo and any subclasses
}
finally
{
    // code to be executed at the end of the block regardless
    // of outcome (successful or exceptional completion)
}
There are two types of exceptions: a base Exception (a checked exception) and a RuntimeException (an unchecked exception).  While both can be used to indicate that an error has occurred and that the developer should take corrective action, RuntimeExceptions do not need to be dealt with in code.  The Groovy language requires that exceptions that are not declared as RuntimeException must either be caught or declared in the method definition.
// The following method throws a FileNotFoundException
void method() throws FileNotFoundException
{
    // The following call throws a FileNotFoundException
    // and must be declared or caught
    FileInputStream fis = new FileInputStream(“foo”)
 
    // Attempt to read data from fis
    try
    {
         // throws an IO exception, caught below
         int byte = fis.read()
    }
    catch(IOException e)
    {
         // Rethrow the exception as a runtime exception
         // which does not need to be declared
         throw new RuntimeException(“Failed reading”)
    }
    finally
    {
         try
         {
          fis.close()
     }
     catch(IOException ex)
     {
          throw new RuntimeException(ex)
     }
    }
}

Groovy: Advanced Concepts: Type Systems

Groovy implements a comprehensive type system that allows developers to define items as specific types and convert these items into other types as necessary.  The Groovy type system implements inclusion polymorphism, overloading and type conversions.  Groovy also supports an equivalent to parameterized types via its generics structure.

Inclusion Polymorphism

Groovy implements inclusion polymorphism through classes and subclasses instead of types and subtypes.  When defining a class, as in Java, the developer defines the variables in the class and the methods available in the class.  A developer can then create a second class that extends that class, creating a subclass.
The subclass inherits access to all the protected and public methods and variables provided by the parent class.  It can also be used anywhere the parent class can be used.
abstract class Shape
{
    private int x, y
   
    public int getX() { return x }
    public int getY() { return y }
 
    public void setX(int x) { this.x = x }
    public void setY(int y) { this.y = y }
   
    abstract void draw()
}
 
class Circle extends Shape
{
    private long radius
    
    void draw()
    {
        println "I drew a circle @ ${x},${y} "+
           "with radius ${radius}"
    }
}
 
class Test
{
    static void main(String[] args)
    {
        // Create instance of Circle
        Circle c = new Circle()
        c.radius = 1.4
        // Access the methods from Shape
        c.x = 1
        c.y = 5
 
        // Assign c to a variable of type
        // Shape which works because Circle
        // is a sub class of Shape
        Shape s = c
        s.draw()
    }
}
The above example defines two classes: Shape and Circle.  Shape is an abstract class, meaning it forms a prototype or base class for any subclasses, but cannot be directly instantiated.  This can be considered a partially implemented class.  Like an interface, it defines methods that need to be implemented by any class extending this abstract class.  Unlike an interface, an abstract class may include methods and variables.
In addition to the Java class and interface mechanism, Groovy adds an additional set of capabilities through its traits mechanism.  This mechanism allows a class to extend one or more traits, which adds methods and fields.  This is similar to how JavaScript allows for extending a prototype or existing object with additional fields and methods.  In actuality, traits are defined in code somewhere between an interface and a class.
trait FlyingAbility
{
    String fly() { "I'm flying!" }
}
 
class Bird implements FlyingAbility {}
def b = new Bird()         
assert b.fly() == "I'm flying!"
Groovy allows for implementing multiple traits in a given class, resulting in an equivalent of multiple inheritance in C++.  In an instance where a class implements multiple traits with the same method, the last declared trait will be executed.
trait A
{
    String exec() { 'A' }
}
 
trait B
{
    String exec() { 'B' }
}
 
// When called, the exec command will return the value of
// B.exec() because it is listed last
class C implements A, B {}

Parameterized Types

Groovy supports Java’s generics structure which can be likened to a parameterized type.  For a further description of Java generics, see Generic Abstraction.

Overloading

Groovy supports method overloading, allowing multiple definitions for a method of a given name.  Overloaded methods are differentiated by the parameters passed into the method.  The following example shows the draw method is overloaded with two implementations: one that takes no parameters and one that takes a single int parameter.  Depending on which method is invoked, the class will present two different outcomes.
class Circle
{
    private int x, y
    private float radius
   
    void draw()
    {
        println "I drew a circle @ ${x},${y} "+
           "with radius ${radius}"
    }
   
    void draw(int scale)
    {
        int x = this.x * scale
        int y = this.y * scale
        float radius = this.radius * scale
   
        println "I drew a circle @ ${x},${y} "+
           "with radius ${radius}"
    }
}
Unlike Java, Groovy also offers the ability to overload operators as well as providing method level overloading.

Type Conversions

Groovy supports converting one type into another.  The underlying Java language is strongly typed, meaning that it can define a variable as a specific primitive or class.  Once a variable has been defined, Java allows for converting that variable from one type to another, where applicable, via both casting and coercion.

Casting

Casting instructs the JRE to treat or convert a given variable as a different type of object.  This is accomplished by prefixing a variable or method with the class type to cast to.  At compile time, the compiler will attempt to determine if the cast is valid for the combination of variable/return and target variable.  For example, if the target variable is a parent class for the source variable or method, then the compiler will allow it because any subclass of the target variable will be compatible.  If the target variable is a subclass of the return, then the compiler will allow it and defer to runtime checks.  If the cast is not possible (such as Integer to String), the Java compiler will return an error.
class CastExample
{
    static void main(String[] args)
    {
        // Compile time-check
        Parent p = getChild();
        // Runtime check
        Child c = (Child)getParent();
        // Invalid cast
        Child c = new Object()
    }
 
    static Parent getParent()
    {
        // Child is cast to Parent on return
        return new Child();
    }
 
    static Child getChild()
    {
        return new Child();
    }
}
 
class Parent
{
    // No implementation for this example  
}
 
class Child extends Parent
{
    // No implementation for this example
}
Groovy adds an additional set of explicit conversions though the as <type> instruction.
String s = “42”
int i = s as Integer
This instruction tells the interpreter how to perform the conversion, eliminating any ambiguity that can arise from the Groovy automatic conversion system.

Coercion

In addition to explicit conversions via casts, Groovy also supports implicit casts via coercion.  Within primitive types, Java allows coercing values of storage to be converted into variables of higher storage.  For example, Java can automatically convert a short to an int to a long.  In each case, the second type stores more bits than the source type, allowing the JRE to represent the same value.
short s = 10
int i = s
long i = s
Groovy can also inherits Java’s implicit object to string conversion.  When any Object is assigned to a String variable, Java automatically calls the toString() method that is defined in the base Object class that all Java classes subclass.  This allows Java to get a string representation of any object, even if it’s just the class name and hashcode.

Groovy: Advanced Concepts: Generic Abstraction

In addition to process and data abstraction, Groovy offers a form of generic abstraction.  It accomplishes this by using the underlying Java generics mechanism.  This allows typed collections and other classes that specify at compile time a specific class or interface that can be used with a specific generic.
Generics were added in 2004 with the release of Java 1.5.  Prior to this, Java collections targeted Object only.  This meant that the developer would need to perform a series of casts to coerce the value provided from the collection to the appropriate type.  Not only was this messy, it also offered a higher likelihood of runtime errors due to improperly trying to cast an object from one type to another.
ArrayList old = new ArrayList();
old.add(“A string”);
 
// The required cast to use the stored object as a String
String aString = (String)old.get(0);
 
ArrayList<String> generic = new ArrayList<String>();
generic.add(“a string”);
 
// Accessing an element from a generic does not require
// the cast operation
aString = generic.get(0);
Groovy inherits this Java generics behavior directly, allowing the developer to use the Java generics.
def list = new ArrayList<String>() as ArrayList<String>
list.add(/a string/)
String value = list.get(0)
Not only does this genericity apply to provided classes, the developer can create classes that utilize the same mechanism.  The following example creates a new collection-like object that takes a generic type T.  At compile time, the compiler will check to see that any objects added are of the type or subclass of T as defined in the code.
class GroovyGenericClass<T>
{
    private ArrayList<T> items = new ArrayList<T>()
   
    void add(T t)
    {
        items.add(t)
    }
}
Java generics also offer the ability to specify a base class or interface that a class must extend or implement to be compatible with the generic class.  An interface is a definition of expected behavior of a class, through the definition of methods and constants, that any implementing class must conform to.  In the context of generics, this allows the developer of the generic to define a specific behavior or method that can be expected of any class that is used in the generic.
// Require any class used in the generic to extend
// Comparable (in this case Comparable is an interface
// so the class must implement it)
class GroovyGenericClass<T extends Comparable>
{
    private ArrayList<T> items = new ArrayList<T>()
 
    void add(T t)
    {
        items.add(t)
    }
   
    boolean equals(int index, T t)
    {
        // The compareTo method is defined in the
        // interface Comparable
        return items.get(index).compareTo(t) == 0
    }
}

Groovy: Advanced Concepts: Data Abstraction

Groovy is an object-oriented language that offers an additional layer of scripting capabilities.  Its data abstraction capabilities are derived from this basic architecture.

Packages and Encapsulation

Groovy allows for organizing classes into packages.  Packages are defined using the package keyword and must be defined at the top of the compilation unit.  Groovy offers additional visibility modifiers that apply to members of a package.  Classes can be marked as protected, which results in them being either available only to other classes in the same package.

Objects and Classes

Java is a class-based language.  This means that Java provides a class-based data abstraction and encapsulation strategy.  In fact, apart from primitives, everything in Java is an object.  There are no standalone data structures or functions.  This means that if a class has a variable that is marked as private, no other class can access that variable.  To access the variable, Java recommends methods to be created in the form of getters and setters, keeping the underlying variables private.
In Java classes can extend an existing class through the sub-classing mechanism.  Classes in Java can only extend a single class.
Groovy offers the same method of data abstraction.  One key addition from Groovy is the automatic creation of getter and setter methods for all variables in a class.  This includes non-Groovy-based classes.
public class JavaClass
{
    // This is a private variable only accessible
    // by instances of this class
    private int privateInt;
    private int anotherPrivateInt = 42;
 
    // The following are getters and setters to provide
    // access to the private variable
    public int getPrivateInt()
    {
        return privateInt;
    }
 
    public void setPrivateInt(int value)
    {
        this.privateInt = value;
    }
}
 
class GroovyClass
{
    private int privateInt
}
 
class GroovyExecutableClass
{
    static void main(String[] args)
    {
        JavaClass jc = new JavaClass()
        jc.setPrivateInt(3)
        println(jc.getPrivateInt())
 
        // Accessing the private variable by the
        // automatic getter/setter
        GroovyClass gc = new GroovyClass()
        gc.privateInt = 4
        println(gc.privateInt)
 
        // Note: Groovy automatically provides the
        // same functionality for existing Java classes
        println(jc.anotherPrivateInt)
    }
}
Groovy’s ability to add automatic getters and setters can be useful, but it can be used to break encapsulation in ways that class writers may not expect.  Any public API that contains private variables are now readable and writable by a Groovy script.  This has caused a fair amount of discussion as to whether this is a true feature, bug or issue.
One addition item of note is how Groovy handles data abstraction in the presence of a trait.  Traits are described in Inclusion Polymorphism.

Groovy: Advanced Concepts

Beyond the basic concepts defined to this point, programming languages often implement more advanced concepts.  These can include:
  • Data Abstraction - sometimes known as encapsulation, this is the process of hiding data from the user of a given framework or API.
  • Generic Abstraction - providing common classes that can accept generic data types as arguments
  • Type Systems - the mechanism the programming language uses to defined types and change variables and values between types 
  • Sequencers - these are more advanced flow control and exception handling concepts.
  • Concurrency - the support of performing multiple actions in a simultaneous or simulated simultaneous fashion

Groovy: Basic Concepts: Procedural Abstraction

Groovy offers a Java-based form of procedure abstraction.  The language offers both functions and sequencing aspects to allow a programmer to manage procedures and control flow.

Functions and Methods

Any Java class, and by extension any Groovy class, offers the ability to have methods exposed.  These methods can encapsulate a set of operations, making them reusable.  Also, since they are attached to a class, they can act upon encapsulated data as described in Data Abstraction and Type Systems.
class AnotherExample
{
    private int index;
    private String name;
 
    // Remember, Groovy is public by default
    String toString()
    {
        return name + ":" + index;
    }
}
In addition to class-based methods, Groovy also offers a type of standalone function.  This function can also encapsulate a set of operations and be reused.  The function is not bound to a class, but instead is bound to the script itself, creating a form of JavaScript-like closure.  The function can be bound to a variable and passed into a function for the purposes of callbacks or other instances where a dynamic function needs to be provided to a method.
def callback(def value)
{
    println(value)
}
 
def needsCallback(Closure c)
{
    c(“do something”)
}
 
// Note the use of this to reference the callback
// in the script context
needsCallback(this.&callback)
Note: in Groovy a stand-alone function is called a closure.
For both methods and functions, Groovy supports both function procedure and proper procedure definitions.  Proper procedures are defined by defining a return type of void and function procedures are defined with a return type of an object or primitive.
class Example
{
    void properProcedure(int param1, String param2)
    {
         // do something
    }
 
    int functionalProcedure(int param1, String param2)
    {
         // do something and return a value
         return 0;
    }
}

Parameters and Arguments

When passing parameters into a Groovy method or function, all values are in only and passed by copy.  This means that primitive values are copied into the function for use.
Object values are passed by reference, meaning the reference value, like a pointer in C, is passed in by copy.  The result is an object accessed in a method is the same object from the calling method.
Java does not support passing functions as variables, so Groovy added an operator, the & operator, to represent the equivalent to a function pointer.

Groovy: Basic Concepts: Variables, Storage and Commands

Groovy supports variables for storing values and referencing other objects.

Simple Variables

Groovy supports simple variables.  These variables can contain either a primitive value or a reference to an object.
int i = 0
short s = 4

Composite Variables

Groovy also supports composite variables that can store or reference arrays and maps.  When updating composites, Groovy supports both selective and total updates.
// Define a composite as an array
def comp = [1,2,3]
// Selective update
comp[2] = 4
// Total update
comp = [5,6,7]
As mentioned in the section Arrays, Groovy defaults to arrays being the Java collection object, typically java.util.ArrayList, instead of a static array.  This means that arrays in Groovy are dynamic.  It does support flexible arrays in that a variable may be defined as an array, but through total update, the reference can point to an array of a different size.

Copy and Reference

Groovy supports the reference semantic.  When assigning one variable’s value to another, it will either copy the primitive value or the reference.  Groovy objects to support a clone method that has a similar effect to the copy semantic, however, the implementer will need to determine exactly how the copy occurs.

Lifetime

Variables created in Groovy are created on the heap and are generally defined as local variables.  Each variable is limited to the class that it was defined in, further defined by the block structure.  As each block is closed, the variables defined within that block fall out of scope and are marked for removal.  See the section Scope and Visibility for more information on scope in Groovy.
Because Groovy is a garbage collected language, the lifetime of a variable is impossible to precisely define as the garbage collector runs at arbitrary times and will clean up variables that have been marked for collection.
Groovy does support a form of global variable, but only in the script mode.  In this mode, a global exists for the lifetime of the script execution.  In a traditional class-based mode, variables are restricted to the class they are defined in.  Modifiers to class variables do allow for marking a variable as static, which has the effect of making that variable global to all instances of the class, and if marked as public, available to all instances as well.  This can have an effect of making a static variable as globally available though they are still a member of a class and not a true global.

Pointers

Groovy does not support pointers.  It only supports references as partial replacement for pointers.
Groovy supports several types of commands including skips, assignment, sequential, conditional and iterative commands.

Skips

Groovy supports a form of skip or command.  Groovy supports the Java ‘;’ line terminator as an optional element.  A single ‘;’ is interpreted as a skip.

Assignments

Groovy supports both single and multiple variable assignment.
int a = 1
def b = c = 2

Sequential Commands

Groovy supports sequential commands using the ‘;’ as a separator.

Conditional Commands

Groovy supports two key conditional commands: if-else and switch-case.  Both allow for conditional code execution based on provided values.

if-else

Groovy supports the Java standard if-else conditional structure.  This allows for executing two different blocks of code depending on whether the statement in the if statement evaluates to true or false.
boolean comparison = new Random().nextBoolean()
 
if(comparison)
{
 println "Value was true"
}
else
{
 println "Value was false"
}
Groovy also supports the nested if-else if-else structure.
boolean comparison = new Random().nextBoolean()
boolean comparison2 = new Random().nextBoolean()
 
if(comparison && comparison2)
 println "Both are true"
else if (comparison && !comparison2)
 println "Only comparison is true"
else if (!comparison && comparison2)
 println "Only comparison2 is true"
else
 println "Both were false"

switch-case

Groovy supports the switch-case structure.  The switch statement can accept a single variable and jump to a specific code block indexed with a specific value.  Unlike Java, Groovy can perform a broader set of matching in the case statement, including strings, types and lists of values.  The following example was taken directly from the Groovy language reference.
def x = 1.23
def result = ""
 
switch ( x ) {
 case "foo":
  result = "found foo"
  // let’s fall through
 
 case "bar":
  result += "bar"
 
 case [4, 5, 6, 'inList']:
  result = "list"
  break
 
 case 12..30:
  result = "range"
  break
 
 case Integer:
  result = "integer"
  break
 
 case Number:
  result = "number"
  break
 
 case ~/fo*/:
  result = "foo regex"
  break
 
 case { it < 0 }: // or { x < 0 }
  result = "negative"
  break
 
 default:
  result = "default"
}
 
assert result == "number"

Iterative Commands

Groovy offers the following types of loops: while, for, for in, each and do-while.  The following section covers each of the type of loops available in Groovy and the samples show how to print the numbers 0-9 within the loop.

While

A while starts with a test and as long as the test results in true it will continue the loop.  This behavior is shared with the underlying Java language.
// Definition
// while(<termination>)
// {
//  statement(s)
// }
 
// Example
def i = 0
while(i < 10)
{
println i++
}

For

A for loop works similar to a while loop, except that its definition contains the conditional, the definition of the variable(s) and the code that affects the variable. In operation, the for loop works the same as the while loop in that it will continue looping while the termination comparison evaluates to true.  The initialization and increment elements are optional.
// Prototype
// for(<initialization>;<termination>;<increment>)
// {
//  <statements>
// }
 
// Example
for(int i = 0; i < 10; i++)
{
 println i
}
 
def j = 0;
 
// Example
for(; j < 10;)
{
 println j++
}
One item to note is that as of 2.4, Groovy for loops only support a single initialization parameter in a for loop, while Java can support multiple.  Groovy version 2.6 will offer this functionality.

For In

Groovy offers an alternate form of a for loop that instead of checking for a conditional, the for in loop will loop through each item in a collection (typically a static array or a List).  Other languages implement this function with a separate foreach keyword.
// Definition
// for( <type> <variable> in/: <array/list>)
// {
//  statement(s)
// }
 
// Example using the word in
for(int j in [0,1,2,3,4,5,6,7,8,9])
{
 println j
}
 
// Example using the : instead of in
for(int j : [0,1,2,3,4,5,6,7,8,9])
{
 println j
}

Do-While

The current released version of Groovy (2.4) does not support the do-while loop construct.  This is scheduled to be released in version 2.6.

Each and EachWithIndex

Because Groovy offers closures, it offers an additional form of loop that can be applied to an array, list or map.  It offers similar functionality to the for-in loop, but in a more compact syntax.  Unlike the for-in loop, as Groovy iterates through each member of the collection, it calls the provided function/closure, providing the current item as a calling parameter.
// Definition
// <array/list/map>.each(Closure c)
 
// Print 0-9
[0,1,2,3,4,5,6,7,8,9].each {
 println it
}
 
// Get the index and letter from the list
["Alpha","Bravo","Charlie","Delta","Echo"].eachWithIndex { letter, index ->
 println "${index} -> ${letter}"
}
 
// Iterate through a map, using the variable letter for key
// and name for word
[
 "A":"Alpha",
 "B":"Bravo",
 "C":"Charlie",
 "D":"Delta",
 "E":"Echo"].each{ letter, name ->
 println "${letter} <-> ${name}"
}
Because closures can be bound to variables, this can allow for more compact coding through the reuse of closures on multiple each or eachWithIndex calls.
// Define the closure
def doSomething(letter,index)
{
 println "${index} -> ${letter}"
}
 
["Alpha","Bravo","Charlie","Delta","Echo"]
 .eachWithIndex this.&doSomething
 
["Foxtrot","Golf","Helo","India","Juliet"]
 .eachWithIndex this.&doSomething

Expressions with Side Effects

Groovy supports expressions with side effects, meaning that an expression, such as a function call or operation, can be used inline with another function call or operation.  The example below shows an example of embedding a function call in an if statement.
if(getCurrentState())
{
}

Groovy: Basic Concepts: Expressions

Expressions are constructs that are evaluated to yield a value.  Groovy supports expressions such as literals, constructions, functions and conditionals.

Literals

Number literals in Groovy can be defined as integer, decimal, octal, hexadecimal or binary.  These can be signed as either positive, implicitly, or negative, explicitly using the hyphen symbol.
int binaryLiteral = 0b110101
int octalLiteral = 07189
int base10Literal = 12229
int hexLiteral = 0x1AC4
float decimalLiteral = 1.234
In addition to simple numerical definition, Groovy inherits Java’s support for including underscores in a long number for readability (eg: int a = 123_456_789).  It also supports forcing numbers to a specific type by using suffixes:
Type Suffix
BigInteger G or g
Long L or l
Integer I or i
BigDecimal G or g
Double D or d
Float F or f
For String literals, Groovy defines the following forms: single quoted, double quoted, triple quoted, slashy and dollar slashy.
Single quoted strings are literals that are:
  • Denoted by a list of characters surrounded by a pair apostrophe (') characters
  • Implements string interpolation
  • Must be on a single line
String aString = 'a single quoted string'
Double quoted strings are literals that are:
  • Denoted by a list of characters surrounded by a pair of quotation (") characters
  • Implements string interpolation
  • Must be on a single line
String aString = "a double quoted string"
Triple quoted strings are literals that are:
  • Denoted by a list of characters surrounded by a pair of three apostrophe characters (''')
  • Does not implement string interpolation
  • Can span multiple lines
  • New lines can be removed by using the \ escape character a the end of the line
String aString = '''First line
A second line
A third line\
continued '''
Slashy strings are literals that are:
  • Defined by a list of characters surrounded by a pair of forward slash (/) characters
  • Implement string interpolation
  • Useful for managing regular expressions
  • Can span multiple lines
  • Empty strings cannot be represented as this type of literal
String aString = /.*foo.*/
Dollar slashy strings are literals that are:
  • Defined by a list of characters surrounded by $/ and /$
  • Can span multiple lines
  • Implements string interpolation
  • Uses a $ as an escape character
def dollarSlashy = $/
 Hello $name,
 today we're ${date}.
 
 $ dollar sign
 $$ escaped dollar sign
 \ backslash
 / forward slash
 $/ escaped forward slash
 $$$/ escaped opening dollar slashy
 $/$$ escaped closing dollar slashy
/$
String escape sequences:
Character Meaning
\t tabulation
\b backspace
\n newline
\r carriage return
\f Form feed
\\ backslash
\ single quote (for single quoted and triple single quoted strings)
\" double quote (for double quoted and triple double quoted strings)
\u#### a Unicode character

Constructions

Groovy allows for constructing composite values in code.  Examples include arrays and maps.
// Create an array in Groovy
def array = [1,2,3]
array << 4
It is possible to coerce Groovy into creating a literal, fixed-length array (ie: <type>[]) either by defining it as the specific data type or using the keyword as.
// Defined as a fixed size int primitive array
int[] intArray = [1,2,3]
// Defined internally as a fixed size long primitive
// array
def longArray = [1,2,3] as long[]
In addition to single-dimensional arrays, Groovy allows for creating multi-dimensional arrays.
def multiDim = [[1,2,3],[4,5,6]]
Defining a value in Groovy is accomplished in a similar method to Java, C or C++.
// Example variable definitions in Groovy
// datatype variablename (= optionalvalue)
def name = “A name”
int i = 0
long l = 123
Maps are created using the following notation:
// Define a map with three key-value pairs
def colors = [red:'FF0000', green:'00FF00', blue: '0000FF']

Function Calls

Groovy supports function calls, known as operations, as part of the base language.  These include:
Operators Precedence
Postfix expr++ expr--
Unary ++expr --expr +expr -expr ~ !
Multiplicative * / %
Additive + -
Shift << >> >>>
Relational < > <= >= instanceof

Conditional Expressions

Groovy supports the following conditionals:
Operator Precedence
Equality == !=
bitwise AND &
bitwise exclusive OR ^
bitwise inclusive OR |
logical AND &&
logical OR ||
Ternary ? :
Groovy also offers regular expressions as a form of conditional operator.  They come in two forms, the find and match operator.  The find operator returns a Java object which when evaluated as a conditional transparently calls the find() method.  The match operator simply returns a Boolean value.
// Example find
def text = "some text to match"
def m = text =~ /match/
assert m instanceof Matcher
if (!m) {
throw new RuntimeException("Oops, text not found!")
}
// Example match
m = text ==~ /match/
assert m instanceof Boolean
if (m) {
throw new RuntimeException("Should not reach that point!")
}

Iterative Expressions

Groovy supports a form of iterative expression in the form of the each and eachWithIndex methods.  For more details see the Loops section.

Constant and Variable Accesses

Constants and variables in Groovy are accessed by their defined name.  In both instances, accessing the variable will return its current value.  Constants in Java are defined as variables with the final modifier instructing the compiler that the value of the variable cannot change, emulating a constant.
For objects or maps, Groovy supports access the values via a ‘.’ notation where the variable is accessed in the form of ParentObject.variable.  Maps work in a similar manner where the form is Map.Key.
class Foo
{
 int val;
}

Foo f = new Foo()
// Dot notation for accessing members of an object
f.val = 7
 
// Define a map with three key-value pairs
def colors = [red:'FF0000', green:'00FF00', blue: '0000FF']
 
// Accessing the values can occur using the []
// notation or by the "." notation
assert colors['red'] == 'FF0000'
assert colors.green == '00FF00'
Groovy offers an additional variable access operator called the safe navigation operator.  This allows for accessing an object reference that may, or may not, have been defined.
def person = Person.find { it.id == 123 }
def name = person?.name
assert name == null

Groovy: Basic Concepts: Values and Types

Groovy as a language offers support for built-in primitive and defined primitive types.  Unlike Java, Groovy is an optionally typed language, accomplished by adding a variant data type.  Depending on the type of data stored, Groovy (like Java) will store either the actual value or a reference to the object.

Built-in Primitive Types

The Groovy language inherits all the Java primitive types:
Type Description
boolean A data type representing 21 values (programmatically defined as true and false)
byte An 8-bit number from -128 to 127 inclusive
char A single 16-bit Unicode character with values from \u0000 to \ufff inclusive
short A 16-bit signed integer with values from -32,768 to 32,767 inclusive
int A 32-bit signed integer with values from -231 to 231-1 inclusive
long A 32-bit signed integer with values from -263 to 263-1 inclusive
float A single-precision 32-bit IEEE 754 floating point number
double A double-precision 64-bit IEEE 754 floating point number
A primitive is stored in memory as the actual value instead of a reference to an object.  However, as with Java, Groovy offers access to object-based representations of these objects.
In addition to the above primitive Groovy adds a keyword of def.  This provides an untyped variable that supports runtime evaluation of type.  See the following examples from the Groovy language documentation below:
def a = 1
assert a instanceof Integer
 
// Integer.MAX_VALUE
def b = 2147483647
assert b instanceof Integer
 
// Integer.MAX_VALUE + 1
def c = 2147483648
assert c instanceof Long
It should be noted that a variable defined using the def keyword is stored not as a primitive, but as the corresponding Java object.

Defined Primitive Types

Groovy supports creation of enumerations as a type of defined primitive type.  Enumerations are a collection of named values.
enum DefinedPrimitive
{
 VALUE1, VALUE2, VALUE3
}

Composite Types

In addition to the defined primitive types, Groovy supports composite types including maps and arrays.

Arrays

In addition to single values, Groovy allows for arrays of multiple individual primitive or complex values.  By default, Groovy will, unlike in Java, automatically create a Java collection, java.util.ArrayList by default, meaning the size of the array is dynamic.  It is possible to create an array as a true, fixed size array of primitives as well.

Maps and Objects

As Groovy is an object-oriented language, variables can also store references to objects.  These objects contain more complex data structures and a collection of methods that can act upon the data stored in the object.  Class definitions and operations are described in a later section.
One special kind of object is a map.  Known as a dictionary or associative array in other languages, a map in Groovy allows for storing key-value pairs in a variable.  The key is typically a string and the value can be any object.

Strings

As described earlier, Strings are defined in Groovy as an object.  The language has support for String literals, which are defined as a chain of characters.  A Groovy string also can perform runtime value substitution.  When printing a string in Groovy, the language will find specified character sequences, ${value/expression}, and replace those with the evaluated value.

Groovy: Historical Background

Groovy as a language was announced in August 2003 with a post by James Strachan on his blog. In it he described a desire to create a dynamically typed scripting language that built upon the Java Virtual Machine / Java Runtime Engine instead of being a separate language with a separate runtime.
When investigating how to begin the language, Strachan looked at Jython, Beanshell and Rhino; and, while finding them close, he asserted that their implementation was language first, then integration with the JVM second.  This resulted in languages that, according to him, “don’t quite sit nicely in a Java (platform and language) developer’s toolkit”.  With those issues in mind, Strachan and other developers began to build what is now the Groovy language.
Given that the team creating Groovy was smaller than the engineering team behind Java, one of the key drivers was to let Java do what it does well and let Groovy fill in the gaps.  To quote Dr. Paul King: “Don’t do all things but do the things you do well.” [2]  In addition to using key elements of Java, they borrowed heavily from other languages, including, but not limited to the following:
  • Metaprogramming capabilities and range data type were borrowed from Ruby
  • The list/map literal notation and the syntax for default parameters were borrowed from Python
  • The collection processing methods, collect and inject, followed Smalltalk’s naming scheme
  • Closures came from the world of functional programming
Key Milestones (pulled from the following sources: Wikipedia, Java Community Process, and the links below):
  • August 2003: Groovy Language announced via blog post
  • March 2004: Groovy was submitted to the Java Community Process as JSR (Java Specification Request) 241
  • January 2007: Groovy version 1.0 is released
  • 2007: G2One was formed to provide training and support for the language, including the then leaders of the Groovy project
  • 2007: Jonathan Strachan leaves the project, though date is uncertain as his departure was never formally announced.
  • December 2007: Groovy version 1.5 is released
  • November 2008: SpringSource acquired Groovy and the Grails company
  • August 2009: SpringSource is acquired by VMware
  • July 2, 2012: Groovy version 2.0 is released
  • 2013: The Groovy language is moved to the Pivotal Software
  • April 2015: Moved to Apache Software Foundation (ASF) incubator
  • November 2015: Moved to top level project in ASF
While the Groovy language was not targeted at a specific industry or vertical sector of the programming language market, like ADA for example, it has been embraced in web development circles, including the Grails web application development framework.  It also provides the core language for Samsung’s SmartThings home automation platform.

Groovy: Introduction

The Groovy programming language is a modern, high-level scripting and programming language that targets the Java Virtual Machine (JVM).  It derives heavily from the Java programming language, adding key elements such as a scripting framework and an optionally typed variable semantic.  The result is a language that, for a seasoned Java developer, has a lower learning curve than Python but that can be used to rapidly create scripts and classes.
Groovy has an unusual design in that it can be both runtime evaluated, like Perl or Python, but can also be compiled into Java byte code.  This allows for greater flexibility and integration with the JVM, but at the same time, it can result in different definitions of key programming terms and concepts depending on the context.
Please note that in this document, Java and Groovy will often be used in interchangeable ways.  This is because the Groovy language is so closely tied to the Java language that in describing one the other is described.  If there are distinct differences, these will be called out directly.

Groovy: Basic Concepts: Binding and Scope

Binding and scope define how a language manages defining, storing and accessing variables and the data contained or referenced by that variable.  This section describes how Groovy manages variable/function binding and scope.

Type Binding

Groovy uses a hybrid of static and apparent dynamic typing.  Because Groovy is a superset of Java, it can utilize the compile time binding and type definition of the Java language.  However, to increase the flexibility of the language, Groovy added an additional layer of dynamic-like typing.  It accomplishes this through the def keyword which creates an un-typed variable.  This type allows the Groovy interpreter/cross-compiler to perform a runtime evaluation and value interpretation.  Under the covers, Groovy treats any variable defined by the def keyword as a subclass of Object.
Groovy, when executing in script mode, does not require that variables are explicitly defined offering the option to implicitly define them as in Perl or other languages.  However, if the value is implicitly defined, then it contains a separate scope than an explicitly defined variable.  See Scope below for a further definition of how Groovy works with scope.

Scope

Scoping defines where a variable can be accessed. This section describes how Groovy manages scope.

Scope and Visibility

Groovy is a nested block-based language, like Java.  This means that Groovy follows the block scope concept where a variable’s scope is limited to the inner-most block that it exists in.  For example, a variable defined inside a loop or other block structure only exists within that block.
Groovy also offers a class grouping through the use of packages.  This allows the developer to group a set of related classes together.  In the context of scope, this affects the class and instance level variables and methods, specifically in where they can be invoked.  Packages are defined as follows:
package name.with.dots
When defining a variable at a class or script level, the language offers three levels of visibility protection: public, protected and private.  Public variables and methods are available to any class within any package.  Protected variables and methods are limited to access within other classes in the same package.  Private variables are restricted to instances of that class only.  In Java, the default visibility for a method or variable is protected.
When a Groovy application is written with classes, it follows the standard Java-based scoping as defined above.  One difference with Java is that Groovy marks variables and methods as public by default instead of protected.  The following example shows example Groovy code written in the class style and executed in the runtime interpreter.
class ExampleClass
{
    // Statically defined variable
    private static def STATIC_STRING =
             "A static string"
 
    def createString()
    {
         return STATIC_STRING + "," +
           System.currentTimeMillis()
    }
 
    public static void main(String[] args)
    {
        ExampleClass ec = new ExampleClass();
   
        AnotherExample ae = new AnotherExample()
        // Accesses the automatic getters/setters
        ae.index = 1
        ae.name = ec.createString()
        println ae
    }
}
 
class AnotherExample
{
    private int index;
    private String name;
 
    // Remember, Groovy is public by default
    String toString()
    {
        return name + ":" + index;
    }
}
This code will generate the following output:
A static string,1510640317383:1
However, Groovy can also run in either an interactive or script based mode.  When a Groovy script is executed, scope is modified slightly.  Specifically, variables defined with a type (def, int, etc) are bound to the script itself.  This means any methods, called closures in Groovy, defined in the script will not have access to that variable.  If a variable’s type is not specified, it is given a global scope.  The mechanics of how Groovy deals with script mode will be described in the Object-Oriented Paradigm section.
The following example will demonstrate the scoping of variables in Groovy.
def useGlobal()
{
    // This will work as its a global
    println "In useGlobal: aGlobal = " + aGlobal
    aGlobal = 4
}
 
def useLocal(def variable)
{
    variable = 4
    println "In useLocal variable = " + variable
}
 
def failOnLocal()
{
    // This will throw an exception
    println aLocal
}
 
// Define the variable globally (available to all
// methods)
aGlobal = 1
// Define it local to the script
def aLocal = 1
 
println "In script aGlobal = " + aGlobal
useGlobal()
println "In script aGlobal = " + aGlobal
 
println "In script aLocal = " + aLocal
useLocal(aLocal)
println "In script aLocal = " + aLocal
 
failOnLocal()
Given the above script, the following output is generated:
In script aGlobal = 1
In useGlobal: aGlobal = 1
In script aGlobal = 4
In script aLocal = 1
In useLocal variable = 4
In script aLocal = 1
Exception thrown
In this example, aGlobal is treated as a global variable and is accessible both in the script itself and any of the defined functions.  The variables aLocal and variable are scoped more narrowly.  The variable aLocal is scoped to the script itself and is not directly available to any closures.  The variable v is scoped to the useLocal function only.

Storage Binding and Lifetime

Java, and by extension Groovy, allows for static binding of variables storage.  They accomplish this through the static keyword.  Any variables or functions defined with this modifier will be allocated storage during compile time and be readily accessible.  Other elements in a Groovy application are dynamically allocated storage at runtime.  These elements include non-static, class and method level variables as well as any object instances created during execution.  Groovy also offers a final keyword which marks a variable as readable but not updateable.

Declaration

Variable declaration defines the type, name and other elements.  This section describes these elements.

Type

Groovy does not support the declaration or re-declaration of types.

Constant

Groovy does support a form of constant through the use of the final and static keywords.  Variables marked as final are identified as non-modifiable and static indicates that a variable is available throughout the lifetime of the program execution.

Variable

Groovy allows for creating variables to store values, manage composite values and reference objects.  In defining a variable name, Groovy allows for names using a mixture of characters and numbers.  The following rules apply:
  • Variables must start with a character or a dollar sign ($)
  • Variables must not start with a number
  • They can include characters A-Z, a-z, \u00C0 to \u00D6, \u00D8 to \u00F6, \u00F8 to \u00FF and \u0100 to \uFFFE
  • It must not be a reserved keyword, such as as, for or while
  • Quoted identifiers are allowed after a dot (.) in a dotted expression.

Procedure

Groovy defines procedures in a similar manner to C, C++ and Java.  It takes the form of:
<return type> name(<parameter list>)
If a procedure is declared in a class it can optionally be prefixed with a visibility modifier.  In script mode there are no visibility modifiers.

Sequential and Recursive

Groovy supports sequential and recursive declaration in both class and script modes.

Blocks

Groovy is a block based language, with blocks defined by a pair of curly-braces ‘{}’.  Blocks control the scope of a variable, as discussed in the section Scope.  It also provides a collection of commands that can be assigned to a function.

Groovy: Basic Concepts

In presenting a new programming language, there are a number of basic concepts that are common to all programming languages.  What is different is the way they are expressed.  These basic concepts include:

  • Values and Types - how the programming language defines the data types it uses and how it manages storing values.
  • Expressions - statements and elements that express a concept in the language.  These can include things like literals, iterative expressions and built in function calls
  • Variables, Storage and Commands - This section combines managing simple and composite variables as well as several command types, such as if/then and switch/case
  • Bindings and Scope - in a programming language, when a programmer defines a variable two key bindings occur: the variable name to the value and the variable name to its type.  Once this happens, how long the variable stays bound is governed by scope.
  • Procedural Abstraction - when building an application or program, there will be a need to encapsulate functionality into reusable blocks.  This is called procedural abstraction and can include functions and methods, plus the arguments provided to them.

Before beginning, a few key concepts and items to understand:

At its core, Groovy is a Java-based language. Because it targets the Java Virtual Machine as its runtime environment, it derives much of its syntax and capabilities from the native Java language. However, it provides a set of extensions that allow it to offer additional capabilities not found in the core Java language specification.

These include closures, optional typing, scripting capabilities and functional programming. This section will review the basic elements of the Groovy language, specifically trying to point out where the Groovy language differs from Java.

One key item of note, especially when reading the following examples, Groovy treats the ';' line terminator as optional, so most of the examples omit it for brevity.