Groovy uses a similar syntax to Java although in Groovy semicolons are optional.
This saves a little typing but also makes code look much cleaner (surprisingly so for such a minor change). So normally if one statement is on each line you can ommit semicolons altogether - though its no problem to use them if you want to. If you want to put multiple statements on a line use a semicolon to separate the statements.
def x = [1, 2, 3]
println x
def y = 5; def x = y + 7
println x
assert x == 12
If the end of the line is reached and the current statement is not yet complete it can be spanned across multiple lines. So for things like method parameters or creating lists or for complex if expressions you can span multiple lines.
def x = [1, 2, 3, 4, 5, 6] println( x ) if (x != null && x.size() > 5) { println("Works!") } else { assert false: "should never happen ${x}" }
Comments
The characters "//" begin a comment that last for the rest of the line.
print "hello" // This is a silly print statement
The characters "/*" begin a comment that lasts until the first "*/".
/* This is a long comment about our favorite println */ println "hello"
The character "#" is not a comment character.
// This doesn't work:
# Bad comment
Method calls
Method calling syntax is similar to Java where methods can be called on an object (using dot) or a method on the current class can be called. Static and instance methods are supported.
class Foo {
def calculatePrice() {
1.23
}
static void main(args) {
def foo = new Foo()
def p = foo.calculatePrice()
assert p > 0
println "Found price: " + p
}
}
Notice that the return statement is optional at the end of methods. Also you don't need to specify a return type (it will default to Object in the bytecode if none is specified).
Optional parenthesis
Method calls in Groovy can omit the parenthesis if there is at least one parameter and there is no ambiguity.
println "Hello world" System.out.println "Nice cheese Gromit!"
It is also possible to omit parenthesis when using named arguments. This makes for nicer DSLs:
compare fund: "SuperInvestment", withBench: "NIKEI" monster.move from: [3,4], to: [4,5]
Named parameter passing
When calling a method you can pass in named parameters. Parameter names and values are separated by a colon (like the Map syntax) though the parameter names are identifiers rather than Strings.
Currently this kind of method passing is only implemented for calling methods which take a Map or for constructing JavaBeans.
def bean = new Expando(name:"James", location:"London", id:123) println "Hey " + bean.name assert bean.id == 123
Passing closures into methods
Closures are described in more detail
here. Closures can be passed into methods like any other object
def closure = { param -> param + 1 }
def answer = [1, 2].collect(closure)
assert answer == [2, 3]
Though there is some syntax sugar to make calling methods which take a closure easier. Instead of specifying parenthesis, you can just specify a closure. e.g.
answer = [1, 2].collect { param -> param + 1 }
assert answer == [2, 3]
The above code is equivalent to the previous code, just a little more groovy. If a method takes parameters you can leave the closure outside of the parenthesis (provided that the closure parameter is the last parameter on the underlying method).
def value = [1, 2, 3].inject(0) { count, item -> count + item }
assert value == 6
The above code is equivalent to the following (but just neater)
def value = [1, 2, 3].inject(0, { count, item -> count + item })
assert value == 6
Important Note
Note that when using the neater syntax for specifying closures either without parenthesis or by specifying the closure after the parenthesis, the closure must start on the same line. i.e. the { symbol must be on the same line as the method call statement. Otherwise the parser interprets the { as a start of a block.
For a in depth description of what kind of method signatures Groovy supports see the Extended Guide to Method Signatures
Dynamic method dispatch
Groovy always uses dynamic dispatch, even if a variable is constrained by a type. The type of the variable only ensures that the variable is at least of that type and avoids you assigning a String to for example int. Dynamic method dispatch is often referred to as dynamic typing whereas Java uses static typing by default.
def dynamicObject = "hello world".replaceAll("world", "Gromit") dynamicObject += "!" assert dynamicObject == "hello Gromit!" String staticObject = "hello there" staticObject += "!" assert staticObject == "hello there!"
Properties
These are described in more detail in the Groovy Beans section.
To access properties you use dot with the property name. e.g.
def bean = new Expando(name:"James", location:"London", id:123) def name = bean.name println("Hey ${name}") bean.location = "Vegas" println bean.name + " is now in " + bean.location assert bean.location == "Vegas"
The above uses a special bean called Expando which allows properties to be added dynamically at runtime.
An Expando is a Map which behaves as a dynamic bean: adding new key/value pairs add the equivalent getter and setter methods, as if they were defined in a real bean.






