Listing A.7 Escaping Quotes println 'double "quotes" are easy' println "or \"escape\" them" println "single 'quotes' are easy too" Single and double quotes can be used within heredocs, a
Trang 1Embedded Quotes
Quotes can be embedded in strings with Groovy in a natural way If you want to embed double
quotes, you can use single quotes to define the string Likewise, the same is true if single quotes
are to be embedded Groovy also supports the usual escaping of quotes (see Listing A.7)
Listing A.7 Escaping Quotes
println 'double "quotes" are easy'
println "or \"escape\" them"
println "single 'quotes' are easy too"
Single and double quotes can be used within heredocs, as shown in Listing A.8
Listing A.8 Quotes in Heredocs
println """
"double quotes"
'single quotes'
"""
Getters and Field Pointers
When class variables are defined in Groovy, we can access those fields using the “.” (dot)
opera-tor We can modify that behavior or retrieve the variable by providing our own getter method (see
Listing A.9)
Listing A.9 Changing Default Variable Access
class BarClass{
def var = "this is bar"
def getVar(){
return "**$var**"
}
}
def bar = new BarClass()
println bar.var
The output from this code would be ”**this is bar**” Although this can be useful, there may
be times when you would want to get access to the fields, bypassing the getter To do this, you
need to create a field pointer, as shown in Listing A.10
Trang 2Listing A.10 Field Pointer
class BarClass{
def var = "this is bar"
def getVar(){
return "**$var**"
}
}
def bar = new BarClass()
println bar.@var
The output of this code is ”this is bar”, which is the exact text in the variable bypassing the
getter method We can also assign this field pointer to a variable and use the variable to access the
field (see Listing A.11)
Listing A.11 Assigning a Field Pointer to a Variable
def varPtr = bar.@var
println varPtr
What might be a bit confusing is that this does not work for setters We cannot use varPtr to
set bar.var Likewise, you cannot access a custom setVar method with the dot operator; you must
explicitly call your custom setVar method
Parentheses and Method Pointers
We noted earlier that parentheses are optional, but this isn’t true in all cases No-arg methods
require that parentheses be present, as shown in Listing A.12
Listing A.12 No-arg Method
def foo = "Hello Groovy World!"
println foo.toUpperCase()
It is possible to overcome this by using a method pointer To do this, you define a variable
that is the pointer to the method using the ampersand (see Listing A.13)
Listing A.13 Setting a Method in a Variable
def foo = "Hello Groovy World!"
def fooUpper = foo.&toUpperCase()
println fooUpper
Trang 3Return Statements
Return statements are also optional for methods The last line in a method is an implicit return
statement As shown in Listing A.14, you can use return or safely leave it off
Listing A.14 Implicit Return Statement
class FooClass
{
Def doIt()
{
"last line"
}
}
foo = new FooClass()
println foo.doIt()
This script, of course, prints “last line” to stdout Any return type is allowed; it’s just a
mat-ter of which is the last line in the method If the last line cannot be evaluated, a null is returned
Listing A.15 will always return null
Listing A.15 Another Implicit Return Statement
class FooClass
{
Def doIt()
{
if(true){"last line"}
}
}
foo = new FooClass()
println foo.doIt()
If we want to return the string, we must explicitly use the return statement, changing the
if statement to the following:
if(true){ return "last line"}
Exception Handling
Exceptions are another optional part of Groovy You can choose to catch exceptions or not
depending on if the code is interested in the exceptions Unlike Java, Groovy doesn’t require that
Trang 4checked exceptions get handled in the code All exceptions are unchecked in Groovy The
deci-sion about the importance of an exception is left completely to the developer
Safe Dereferencing
In Java, there is one unchecked exception that is often caught or defended against by developers:
the dreaded NullPointerException (NPE) In Java, a developer would typically use an if
state-ment guard to protect against NPEs, as shown in Listing A.16
Listing A.16 Protecting from NullPointerExceptions in Java
if(null != foo)
{
foo.doSomething();
}
Groovy provides a nifty bit of syntactic sugar to defend against NPEs—the safe
dereferenc-ing or “?” operator:
foo?.doSomething ()
The “?” operator dispatches calls only when the object is not null So, the toUpperCase
method will only get executed if foo is non-null This makes defensive programming fast and
easy The usual if statement guard a developer might use in Java is traded for a single character
Operator Overloading
Groovy brings operator overloading to Java Table A.1 describes the overloaded operators and the
methods that they map to
All the comparison operators handle nulls gracefully so that NullPointerExceptions don’t
get thrown
Table A.1 Overloaded Operators
(Source: http://groovy.codehaus.org/Operator+Overloading)
a + b a.plus(b)
a – b a.minus(b)
a * b a.multiply(b)
a ** b a.power(b)
Trang 5Table A.1 Overloaded Operators
(Source: http://groovy.codehaus.org/Operator+Overloading)
a / b a.div(b)
a % b a.mod(b)
a | b a.or(b)
a & b a.and(b)
a ^ b a.xor(b)
a++ or ++a a.next()
a or a a.previous()
a[b] a.getAt(b)
a[b] = c a.putAt(b, c)
a << b a.leftShift(b)
a >> b a.rightShift(b)
~a a.bitwiseNegate()
–a a.negative()
+a a.positive()
a == b a.equals(b) or a.compareTo(b) == 0 **
a != b ! a.equals(b)
a <=> b a.compareTo(b)
a > b a.compareTo(b) > 0
a >= b a.compareTo(b) >= 0
a < b a.compareTo(b) < 0
a <= b a.compareTo(b) <= 0
Boolean Evaluation
Groovy boolean evaluation is much different than Java In Groovy, expressions get automatically
evaluated to a boolean true or false The best way to show how things evaluate is by way of
demonstration In Listing A.17, the following evaluate to true
Trang 6Listing A.17 Evaluate to true
if(1) //true
if(-1) //true, all non-zero values evaluate to true
if(!null) //true, non-null values are true
if("foo") //true
foo = ["a","b","c"]
if(foo) //true, non-empty lists, maps and arrays evaluate to true
In Listing A.18, the following evaluate to false
Listing A.18 Evaluate to false
if(0) //false
if(null) //false
if("") //false, empty strings and string buffers evaluate to false
foo = []
if(foo) //false
This should give you a feel for how Groovy evaluates truth
Closures
Groovy’s definition of a closure is essentially a named block of code Listing A.19 is a Groovy
closure in its simplest form
Listing A.19 Very Simple Closure
def foo = { println "I'm a foo" }
foo()
Unsurprisingly, this code produces "I'm a foo" printed to standard out Groovy closures
can also accept parameters; by default, there is a single parameter named "it" (see Listing A.20)
Listing A.20 Default “it” Variable
def foo = { println "I'm a $it" }
foo "bar"
Groovy closures can also accept named parameters, as shown in Listing A.21
Trang 7Listing A.21 Named Parameters
def foo = { a, b ->
println "$a + $b = ${a+b}"
}
foo 3, 4
Finally, closure parameters can be preloaded by using curry (see Listing A.22)
Listing A.22 Using Curry
def foo = { a, b ->
println "$a + $b = ${a+b}"
}
def addTwo = foo.curry(2)
addTwo 4
Curry will accept any number of parameters, preloading the closure parameter’s starting
with the leftmost defined
Lists
Groovy offers convenient syntax for list creation and manipulation (see Listing A.23)
Listing A.23 List Creation
def people = ["alice", "bob", "claire"]
println people.class
The output of this code snippet shows us that by default, a list of type java.util.ArrayList is
created We can manipulate the type by using the as operator (see Listing A.24)
Listing A.24 Manipulating the Type of a List
def people = ["alice", "bob", "claire"] as Set
def people = ["alice", "bob", "claire"] as String[]
Empty lists can be created by just using the square brackets:
def emptyList = []
We can add to a list by using the overloaded left shift operator or the += operator (see
Listing A.25)
Trang 8Listing A.25 Adding to a List
def people = ["alice", "bob", "claire"]
people << "davide"
people += "earl"
println people
This code snippet will output the following:
["alice", "bob", "claire", "davide", "earl"]
The += operator will also concatenate two lists, as shown in Listing A.26
Listing A.26 List Concatenation
def people = ["alice", "bob", "claire"]
def morepeople ["davide", "earl"]
people += morepeople
println people
This code snippet will output the following:
["alice", "bob", "claire", "davide", "earl"]
Retrieving elements from the list can be accessed in either an array style or a list style (see
Listing A.27)
Listing A.27 List Element Access
def people = ["alice", "bob", "claire"]
println people[1]
println people.getAt(1)
As expected, this code snippet will output "bob" twice You can remove the last item in the
list using the pop method, as shown in Listing A.28
Listing A.28 Using the pop Method
def people = ["alice", "bob", "claire"]
println people.pop() //prints "claire"
println people //prints ["alice", "bob"]
Likewise, lists can be sorted and reversed with methods of the same name (see Listing A.29)
Trang 9Listing A.29 Sorting and Reversing a List
def people = ["bob", "alice", "claire"]
people.sort()
println people //prints ["alice", "bob", "claire"]
println people.reverse() //prints ["claire", "bob", "alice"]
Note that the sort method makes a change to the list, whereas the reverse method returns the
reversed list
join is a convenient method that returns a string concatenation of all the elements in a list
separated by any string you pass it (see Listing A.30)
Listing A.30 Using the join Method
def people = ["alice", "bob", "claire"]
println people.join() //prints alicebobclaire
println people.join(",") //prints alice,bob,claire
Another convenient method is findAll This method takes in a closure, which is used to
match items in a list and returns a list with all the matching items (see Listing A.31)
Listing A.31 Using the findAll Method
def people = ["alice", "bob", "claire"]
println people.findAll{ it.startsWith "c" } //prints ["claire"]
Other methods that are available are max, min, and sum—they do what you might expect
(see Listing A.32)
Listing A.32 Using the min, max, and sum Methods
def scores = [70, 60, 90]
println scores.min() //prints 60
println scores.max() //prints 90
println scores.sum() //prints 220
collect is another convenient method that returns a new list modified by the closure it is
passed (see Listing A.33)
Listing A.33 Using the collect Method
def scores = [70, 60, 90]
println scores.collect{ it += 5 } //prints [75, 65, 95]
Trang 10The flatten method flattens multidimensional lists It returns a new flattened list, leaving the
original list alone, as seen in Listing A.34
Listing A.34 Using the flatten method
def scores = [[70, 60, 90], 80, [70, 50]]
println scores.flatten() //prints [70, 60, 90, 80, 70, 50]
Groovy adds an additional operator called the spread operator, “*”, to our list of tools
The spread operator spreads the elements of a list over the parameters of a method call (see
Listing A.35)
Listing A.35 Using the Spread Operator
def order(first, second, third)
{
println "1: $first"
println "2: $second"
println "3: $third"
}
def params = ["Rowan", "Claire", "Sophia"]
order(*params)
Finally the spread-dot operator provides a quick way to iterate over a list, applying the
same method to each item in the list, and returns the results in a new list (see Listing A.36)
Listing A.36 Using the Spread-Dot Operator
def params = ["Rowan", "Claire", "Sophia"]
params*.toLowerCase() //prints ["rowan", "claire", "sophia"]
As you can see, Groovy provides quite a number of convenient methods for
manipulat-ing lists
Maps
As with lists, Groovy provides convenient syntax for dealing with maps (see Listing A.37)
Listing A.37 Creating a Map in Groovy
def gifts = [rowan: "legos", claire: "puppy", sophia: "doll"]
println gifts.get("rowan")
println gifts.sophia