Welcome to the Groovy cheat sheet! This is a condensed reference for Groovy syntax and other information that you might regularly want to look up.
1. Core types and operators
Groovy comes with a selection of the basic types you’d expect, such as strings and numbers. Most of them are part of the standard Java class library, although Groovy introduces some new literals.
1.1. Type list
| Type | Literals | Notes |
|---|---|---|
java.lang.String |
|
Double quotes allow embedded expressions. Slashes mean you don’t need to escape |
java.lang.Character |
|
Represents a single Unicode character. Primitive type: |
java.lang.Boolean |
|
Primitive type: |
java.lang.Byte |
|
8-bit integer. Primitive type: |
java.lang.Integer |
|
32-bit integer. Primitive type: |
java.lang.Long |
|
64-bit integer. Primitive type: |
java.math.BigInteger |
|
No upper limit on values. No primitive equivalent |
java.lang.Float |
|
32-bit, single-precision floating-point number. Primitive type: |
java.lang.Double |
|
64-bit, double-precision floating-point number. Primitive type: |
java.math.BigDecimal |
|
Exact, uncapped floating-point number. No, primitive equivalent. |
java.util.List |
|
Can contain values of any type. |
java.util.Set |
|
Can contain values of any type. |
java.util.Map |
|
String keys don’t need quotes when using the map literal. |
groovy.lang.IntRange |
|
The first literal excludes the upper bound, whereas the second includes it. The lower bound is always included. |
In addition to all the string literal variants shown in the table above, you can create multi-line strings by using three quotes in a rows. For example:
def text = """Dear sir,
Welcome to Top Bank!
"""
You can use single or double quotes, with the latter allowing you to embed Groovy expressions (the behavior matches that of the equivalent normal strings).
Line continuations allow you to split long lines of text across multiple lines of your source code:
def text = """\
one \
two \
three \
"""
assert text == "one two three"
For this to work, you can’t have any characters, even whitespace, after the backslash ('\').
1.2. Coercions
Groovy allow you to easily convert values from one type to another if the conversion is known, for example String → Character, or List → Set. Either declare a variable of the target type:
Set s = [1, 2, 3, 3]
char ch = 'H'
int[] a = [1, 2, 3, 4]
or use the as operator:
def s = [1, 2, 3, 3] as Set
def ch = 'H' as char
def a = [1, 2, 3, 4] as int[]
The as operator is more flexible as it can be used for method arguments too:
assert Character.getNumericValue('H' as char) == 17
Without the coercion, the above code would throw a MissingMethodException.
1.3. Overloadable operators
Groovy allows you to implement operators in your own classes by implementing methods with specific signatures. You can also use the method names to look up what operators are supported by types in the Java class library and Groovy JDK extensions.
Here’s a list of such operators and what they generally mean. Try not to deviate from the semantics when you do your own operator overloading!
| Operator | Method | Semantics |
|---|---|---|
|
a.plus(b) |
Addition |
|
a.minus(b) |
Subtraction |
|
a.multiply(b) |
Multiplication |
|
a.div(b) |
Division |
|
a.mod(b) |
Modulo/remainder |
|
a.power(b) |
Exponentiation |
|
a.or(b) |
Bitwise OR |
|
a.and(b) |
Bitwise AND |
|
a.xor(b) |
Bitwise XOR |
|
a.asType(b) |
Type coercion |
|
a.call() |
Method call |
|
a.getAt(b) |
Array access |
|
a.putAt(b, c) |
Array mutation |
|
b.isCase(a) |
'is one of' |
|
a.leftShift(b) |
Left shift or append |
|
a.rightShift(b) |
Right shift |
|
a.rightShiftUnsigned(b) |
Unsigned right shift |
|
a.next() |
Increment value |
|
a.previous() |
Decrement value |
|
a.positive() |
Make positive |
|
a.negative() |
Make negative |
|
a.bitwiseNegative() |
Bitwise negate |
1.4. Other operators
These operators return true or false based on different types of comparison.
| Operator | Semantics |
|---|---|
|
Value-based equality |
|
Value-based inequality |
|
Less than |
|
Less than or equal |
|
Greater than |
|
Greater than or equal |
|
Compare (returns -1, 0, or 1 if |
|
Regex pattern match. Returns a |
|
Regex pattern exact match. Returns |
|
Null-safe navigation. Returns |
|
Ternary operator (concise if-else). Returns |
|
Elvis operator. Returns value of |
2. Flow control
This section covers conditions, loops, and error handling via exceptions.
2.1. Conditions
The most common conditional in Groovy is the if statement:
if (<expr>) { (1)
...
}
else if (<expr>) { (2)
...
}
else { (3)
...
}
-
Only the
ifis required and must come first. -
You can have as many
else ifas you like. -
You can only have a single
elseand it must come last.
Other notes:
-
The curly braces are optional if the body of the block is only a single statement.
-
<expr> must resolve to
trueorfalseaccording to Groovy Truth (see next sub section).
The only alternative is the switch statement, which is like an extended if-else if-else:
switch (<value>) {
case <value>: (1)
...
break (2)
case <value>: (3)
...
break
default: (4)
...
break
}
-
Matches if this value is the same as the one in the
switch. More generally, matches ifcaseValue.isCase(switchValue)evaluates totrue. -
breakis not required but without it, the followingcasewill always trigger too. -
You can have as many
casestatements as you like. -
If none of the
casestatements match, this will trigger. It is not required.
2.2. Groovy Truth
Groovy will automatically coerce expressions to boolean values where a boolean is required, for example in an if statement. Here are some standard coercions:
| Type | Values equating to false |
Values equating to true |
|---|---|---|
String |
Empty or |
Everything else |
Number |
Zero or |
Everything else |
Collection |
Empty or |
Everything else |
Map |
Empty or |
Everything else |
Matcher ( |
No match found |
At least one match |
2.3. Loops
Groovy has two main loops: for and while. There is no do-while. The predominant syntax for the for loop is:
for (<var> in <value>) {
...
}
where <var> is a typed or untyped variable and <value> is something that can be iterated over, such as a list or a range of numbers. For example, iterating over numbers can be done with:
for (int i in 0..<10) {
...
}
Here’s an example of iterating over a list of strings:
List<String> listOfNames = ...
for (name in listOfNames) {
...
}
Note The above form of for works for any instance of java.lang.Iterable, such as collections and strings.
There is a less common form of the for loop which mimics the behaviour of Java:
for (int i = 0; i < 10; i += 2) {
...
}
This is rarely used and should be avoided if possible. It doesn’t support the , operator that allows initialisation of multiple variables, so it’s not completely consistent with Java. That makes is confusing for people coming from that language.
The while loop is straightforward:
while (<expr>) {
...
}
where <expr> is an expression that can be evaluated to a boolean according to Groovy Truth.
For completeness, another common approach to iteration is with the each() method:
List<String> listOfNames = ...
listOfNames.each { String name ->
...
}
One notable disadvantage of this approach is that Groovy can’t infer the type of the objects in the iterable, so it’s often best to explicitly declare the type of the closure argument. See later for more closure syntax.
2.4. Exceptions
The normal mechanism for error handling in Groovy is via exceptions, same as for Java. Unlike Java, though, Groovy treats all exceptions as runtime ones, which means the compiler does not force you to catch them.
Here is the basic syntax:
try {
// Execute the code that might throw an exception
}
catch (SpecficException ex) { (1)
// Do something with the exception `ex`
}
catch (GenericException ex) {
...
}
finally { (2)
...
}
-
Catch expressions are evaluated in declared order, so the first one that matches the thrown exception wins. Hence you normally order them from most specific to least specific.
-
The
finallyblock always executes, regardless of whether the code throws an exception or not.
Note The try is required, but the catch and finally blocks are optional. You have to have at least one catch or a finally, though.
Throwing an exception is even easier:
throw new MyException()
In other words, you instantiate an exception just like any other object and use it as the argument to throw. You can also use throw to rethrow an exception from a catch block. And just as you can pass arguments when creating normal objects, you can do the same with exceptions. One of the most common arguments (supported by most exceptions) is a message explaining the error:
throw new ConnectException("Credentials are invalid")
If you want to execute the same block of code for more than one different exception, you can use a multi-catch block:
try {
// Execute the code that might throw an exception
}
catch (SpecficException | OtherException ex) {
// Do something with the exception `ex`
}
So in general, a catch takes the form:
catch (<type> [| <type>]* <var>) { ... }
where * indicates 0 or more of what’s in the square brackets.
3. Classes and objects
Groovy is an object-oriented language whose custom types are known as classes. It also support interfaces, which have no implementation and simply define a contract between the caller and callee. In other words, one or more defined method signatures.
3.1. Class definitions
[package <pkg>] (1)
[<scope>] [abstract|final] class ClassName [extends OtherClass]
[implements FirstInterface, SecondInterface] {
[<scope>] [static] [final] def|<type> fieldName [= <value>] (2)
[<scope>] ClassName([<args]) { (3)
// Body
}
[<scope>] [static] [final] def|<type>|void methodName([<args>]) { (4)
// Method body
}
[<scope>] [abstract] def|<type>|void methodName([<args>]) (5)
}
-
Optional package/namespace for the class. Ideally all classes should be in a package.
-
Declares a field or property (see properties section) for storing state. Cardinality: 0..*
-
Declares a constructor that allows you to initialise new instances of the class.
-
Defines a method implementation that can be called from other code.
-
Declares an abstract method, i.e. one that has no implementation and must be implemented by subclasses.
Legend:
-
[…] = something that’s optional.
-
…|… = indicates mutually exclusive options.
-
<pkg> = a dot-separated namespace, e.g. org.example or java.lang.
-
<scope> = a visibility scope that determines what other code has access to the class/field/method. Groovy defaults to
public, i.e. all code has access.protectedis accessible from subclasses and code in the same package (packages are not hierarchical).privateis only accessible from the same class.protectedandprivatedo not apply to classes. -
<abstract> = applies to classes (they can’t be instantiated directly) and methods (they have no implementation and must be implemented in subclasses). If a class has at least one abstract method, it is automatically an abstract class.
-
<final> = declares that a class cannot be subclassed or that a method cannot be overridden.
-
<static> = declares a field that is shared between all instances of the class, or a method that can be called on the class itself, not an instance of the class.
-
<type> = an explicit type, such as
Stringorint. -
<value> = an initial value for a field or property (can be an expression too).
-
<args> = a comma-separated list of method arguments. Each argument is of the form
[<type>] <name>. Cardinality: 0..*. -
extends = declares that this class subclasses another class. You cannot extend more than one class.
-
implements = declares that this class implements the methods defined in the listed interfaces. You can implement as many interfaces as you like.
Here’s an example of a simple class with a property and method:
class Person {
String name
Date dateOfBirth
int getAge() {
return (new Date() - dateOfBirth).intdiv(365)
}
}
Remember that you can replace the types in front of the property names by def if you want to leave them untyped.
3.2. Objects
Objects are instances of classes. To create new objects, you can either use literals, such as those described in the Type list, or the new keyword:
def p = new Person()
The new keyword allows you to instantiate any non-abstract class, while optionally initialising its state. How you initialise the object depends on what constructors are defined. In the case of no constructors or a single default (zero-arg) constructor, you can use GroovyBeans syntax:
def p = new Person(name: "John Doe", dateOfBirth: ...)
3.3. Properties
Properties are an extension of fields based on the JavaBeans API. When you access properties, you always go through getter and setter methods. Groovy automatically generates those underlying methods:
def p = new Person(...)
// All of these work
println "${p.name} (${p.dateOfBirth})"
println "${p.getName()} (${p.getDateOfBirth()})"
p.name = "Peter"
p.setName("John")
Read-only properties are implemented as standalone getter methods:
class Person {
...
String getDisplayDetails() {
return "${name} (${dateOfBirth})"
}
}
def p = ...
println p.displayDetails
Adding a visibility scope to a field disables property behavior, i.e. the getter and setter methods aren’t generated:
class Person {
public String name
}
def p = new Person(name: "Peter")
println p.getName() // Throws MissingMethodException!
The GroovyBeans constructor syntax still works, though. Here are some examples of how property names maps to methods:
| Property name | Method name |
|---|---|
|
|
|
|
|
|
|
|