Groovy basics

Semicolon (;) is optional. It is required only when writing multiple statements on the same line.

Parentheses are optional. If the compiler can figure out where to put them (to generate them) then you do not need to put parentheses.

Function1(Arg1, Arg2, Arg3)

can be written

Function1 Arg1, Arg2, Arg3

In Groovy you do not need to call your file as the class. The reason is that you can put many classes in a single file. Or you can have absolutely no classes in a file.

Once you have a Groovy file, you can simply execute it by giving that file as parameter to the “groovy” command. When you do this, a class is generated, byte-code is generated and then that byte-code is executed. However, that byte-code is not saved somewhere. So… Groovy is not an interpreted language.

If you want to get access to the class (byte-code) you use “groovyc” command. If you want to execute the compiled (byte-code) version you run “groovy” on the generated class file (you provide the class file without the .class extension).

Use “javap” to inspect a generated byte-code and see the classes / methods from it (reflection is being used). If you run “javap” on a byte-code of a groovy script that did not contain any class definition you will see that a class was auto-generated in this case… The class name is the same as the file name and extends groovy.lang.Script and has a “main” method and a “run” method. In case of a script, all the code from the script is being “copied” inside the “run” method. When the script is executed, the generated class is being used to run the “main” method that runs the “run” method. Any variables declared with types in the script become local variables in the “run” method. Any variables that were declared without type become getters / setters in the class itself.

If you want to run a groovy class with “java” command you need to add the groovy-all-x.x.x.jar in the class path in order to allow java to resolve all the Groovy related dependencies.

In Java, “==“ tests the equality of the object references, thus it tests if it’s really the same object. In Java, if you want to test if 2 different objects are equal, you need to explicitly use the equals() method. In Groovy, “==“ is a method overload for the equals() method!!!


    • Used for a variable: I do not know or I do not care about the type of the variable
      • You can assign that variable to values of any type. The data type will be figured out dynamically at run-time.
    • Used for return type in a method: you can return any type you want

In Groovy everything is an object. This is different than Java where we also have the primitive types (e.g. int, char, bool, etc). On Groovy you can do: 5.getClass()


  • single vs double quoted strings
    • Single quoted: this is the classic Java string. It’s represented as a classic Java String object.
    • Double quoted: this string allows interpolation: inserting values (that get first evaluated) into it. Example: “The string value is ${value}”. This is usually represented as groovy.lang.GString.
  • For multi-line strings we have the same 2 flavors: ”’ and “””

Defaults for private / public classifiers
In Groovy, if you do not explicitly specify the classifiers, then you get:

  • Private for attributes
    • For attributes, if you do not explicitly specify the classifier, then the default classifier will be private and Groovy will automatically generate getters and setters for you.
    • Even if the attribute is private, you can use the attribute name for read/write but, behind the scene, Groovy will, in fact, call the public getter/setter to perform the operation.
  • Public for methods
  • Public for the class

Also, in Groovy, you get 2 default constructors:

  • One with no parameters (similar to Java
  • One with mapped parameters (e.g. Person p = new Person(firstName: Mihai, lastName: Fecioru))

Generics in Groovy
Groovy allows compilation of generics, which means that you can write code that is using generics and everything will work as expected. HOWEVER, Groovy will not enforce generics. Meaning, you can declare a list of Strings and you can add Strings, Numbers, Date objects and everything will work. This is very different than Java where generics will be enforced at compile time (but erased at run-time).

A closure is a body of code delimited by braces where you specify first the parameters, then an “->” arrow and then the code that is actually using the provided parameters to do something useful. In case the closure only takes a single parameter, you can use the default “it” name to refer to that parameter.


b.functionTakingClosureAsParameter (function_param1, function_param2, {
                        closure_param1, colsure_param2 ->
                                … code using the params here …

If the closure is the last parameter defined for the function, then you can put the closure outside the parenthesis when calling the function. So, the above example becomes:

b.functionTakingClosureAsParameter (function_param1, function_param2) {
                        closure_param1, colsure_param2 ->
                                … code using the params here …

Spread-dot operator: *.
The spread-dot operator (*.) is used to invoke a method on all members of a Collection object. The result of using the spread-dot operator is another Collection object.


          List names = [“Mihai”, “Dave”, “Serban”]
          println names.collect { it.size() }
          println names*.size()

In both cases we will get a list of sizes for each string: [5, 4, 6]

Safe navigation operator: ?.
This allows to access a field of a variable even if that variable may have null value. Usually, in such a case you would first test that variable for null and after we checked that the value is not null, we can safely use that variable property. With safe navigation we can do:


If variable is null, the result is null. Otherwise, the value of the property is returned.

Spaceship operator: <==>
If you have 2 values of a type that implements Comparable interface (x and y), then

x <==> y

will return -1 if (x < y), 0 if (x == y) or 1 if (x > y).

Elvis operator: ?:
Used to replace (to produce an even shorter form) for the if-then construction. So, instead of:

finalName = name ? name : “Default Name”

You can write:

finalName = name ?: “Default Name”

The “inject” method
Your can use the inject method to implement a “reduce” phase with an initial accumulator value.

myList(initialValue) { acc, val ->
               … // rest of the closure body

In this example, the “acc” starts with the “initialValue” and “val” takes one by one the elements from myList list. Then, the “acc” is updated with the result of each closure execution. At the end, the final value of the “acc” is returned.

The “inject” method also has a version where it does not have a parameter for the “initialValue” but only the closure as the single parameter. In this case, the “acc” is initialised with the first element from the myList list and the “val” is initialised with the second element from the list. The rest of how the “inject” method works remains the same.

Posted in Uncategorized | Leave a comment