Module 1
Groovy Fundamentals
Module Overview
• Differences between Groovy and Java
• Declaring classes
• Using assertions
• Groovy Strings
• Closures
• Lists and Maps
• Expandos
• Ranges
• Lists, Maps, and Sets
• Builders
• Metaprogramming
Java An Overview
• Object Oriented
• Platform Independent
• Simple
• Secure
• Architecture-neutral
• Portable
• Robust
• Multithreaded
• Interpreted
• High Performance – JIT
• Distributed
• Dynamic
Intro. To Groovy
• OOP
• Through Apache Licence
• Optionally compiled
• Runs in JVM
• Compiles down to Java byte-code
• Simplified syntax
• Support both Static and dynamically typed
• Support for operator overloading.
• operator overloading
• Native syntax for lists and associative arrays
• Native support for regular expressions
• Native support for various markup languages
• You can use existing Java libraries
• Groovy extends the java.lang.Object
Differences between Groovy and Java
• Default imports
• Multi-methods
• Array initializers
• Package scope visibility
• ARM blocks - Automatic Resource Management
• Inner classes
• Static inner classes
• Anonymous Inner Classes
• Creating Instances of Non-Static Inner Classes
• Lambdas
• GStrings
• String and Character literals
• Primitives and wrappers
• Behaviour of ==
• Conversions
• Extra keywords
Default imports
• All these packages and classes are imported by default
• java.io.*
• java.lang.*
• java.math.BigDecimal
• java.math.BigInteger
• java.net.*
• java.util.*
• groovy.lang.*
• groovy.util.*
Multi-methods
• methods which will be invoked are chosen at
runtime.
• Same in Java and Groovy, but it will behave differently:
• int method(String arg) { return 1; }
• int method(Object arg) { return 2; }
• Object o = "Object"; int result = method(o);
Array initializers
• { … } block is reserved for closures.
• Unsupported
• int[] array = { 1, 2, 3}
• Supported
• int[] array = [1,2,3]
•
Package scope visibility
• omitting a modifier on a field doesn‟t result in a
package-private field like in Java:
• Instead, private field, an associated getter and an
associated setter
• to create a package-private field by annotating it
with @PackageScope
Closures
• Following
• Can be written as
Inner classes
• Static inner classes
• Anonymous Inner Classes
• Creating Instances of Non-Static Inner Classes
Static inner classes
Anonymous Inner Classes
Creating Instances of Non-Static Inner Classes
UnSupported Supported
Lambdas
Groovy Java
Java 8 supports lambdas Has Closures
Runnable run = () -> Runnable run = { println
System.out.println("Run 'run' } list.each { println
"); it } // or
list.forEach(System.out: list.each(this.&println)
:println);
Scripting Languages
The old new new thing…
• Productivity / Rapid Development / Agile
• Interpreted (No Compile Cycle)
• Expressive - Shorter, Less Verbose Syntax
• Feature Rich yet Simple and Productive
• Shell / System Integration / Systems “Glue”
• Dynamic
• Open Source – also code available by default
• Advanced languages features Closures / Mix Ins
16
Scripting Languages – Productivity
Productivity - Lines of code compared to C
7
6
5
4
3
2
1
0
lk
va
l
++
C
n
an
r
si
Pe
ho
lta
Ja
C
Ba
r tr
al
t
Py
Fo
Sm
al
su
Vi
S
M
From “Code Complete” by Steve McConnell
17
Scripting Languages – The Reputation
• Weakly Typed
• Procedural
• Scalability / Enterprise Ready
• Not Maintainable – (Perl)
• Lack of threading support
• Lack of IDE / Debugger support
• Cross Platform Support
• Performance
• Specialized / Not general purpose
18
Scripting Languages – The Reality
• The lines are blurring between scripting and
traditionally compiled languages. This trend will
continue.
• Programmer adoption going up, up, up.
• Ruby on Rails, PHP are popular, powerful,
productive and cool.
• Many now target a Java VM‟s (JRuby, Jython,
ABCL) or Perl targets Parrot.
• Optimize developer time over execution time.
• The right tool for the right job.
19
Groovy – In the Sweet Spot
Groovy is feature rich and java friendly
20
Groovy - Overview
• Syntactically very close to Java
• Leverages investment in Java
• Interpreted-ish. .groovy files fully parsed and
classes are generated on the fly, via a custom class
loader.
• Can be compiled and fully integrated with
traditional Java application.
• Language level support for lists, maps, regular
expressions.
• Supports closures, dynamic typing, meta object
protocol.
21
Groovy & Java – Seamless Integration
• Groovy code co-exists with Java Code and runs in
the JRE.
• Syntax nicely aligned with Java.
22
Direct or Precompiled Modes
23
Groovy – Current Situation
• Standards Supported - JSR-241 - Groovy is the
2nd standard language for the Java platform, with
Java being the first.
• Still in Beta – Jsr-6 (released: end of June 2006)
• RC1 – The first release candidate of the Reference
Implementation – was due end of August 2006.
• Pretty stable but wouldn‟t bet my job on it.
• Error messages still hard to decipher.
• Documentation lacking.
• Groovy in Action Book from Manning. 90%
available for download via Early Access Program.
24
Hello World – Groovy Style
println 'Hello Groovy'
To run type „groovy hello.groovy‟
• Parenthesis are optional
• Ending semi-colons optional
• Class declaration optional
• Main entry point optional
• Single Quotes or Double quotes for Strings. Groovy
has several string styles.
• System.out is assumed - Groovy automatically
imports the packages groovy.lang.*, groovy.util.*,
java.lang.*, java.util.*, java.net.*, and java.io.*
25
Groovy Types
• Everything is an object no primitive types.
• Primitive types are auto boxed
• Optional Typing – If not explicitly specified assumed
to be java.lang.Object
• Type safe – Unlike some scripting languages, Groovy
doesn‟t allow one type to be treated as another
without a well defined conversion being available.
26
Types Example
a=1 // Implicit typing to Integer
b = 'howdy' // Implicit typing to String
int c = 33 // Explicit typing to Integer
def d = 5.2f // def keyword means any type
println 'a is ' + a.class.name
println 'b is ' + b.class.name
println 'c is ' + c.class.name
println 'd is ' + d.class.name // class name as
property
Output
a is java.lang.Integer
b is java.lang.String
c is java.lang.Integer
d is java.lang.Float
27
Operator Overloading
Operator Method Operator Method
a+b a.plus(b) a << b a.leftShift(b)
a–b a.minus(b)
a >> b a.rightShift(b)
a*b a.multiply(b)
a >>> b a.rightShiftUnsigned(b)
a/b a.div(b)
a%b a.mod(b) switch(a){
a++ or case b:
++a a.next() } b.isCase(a)
a-- or --a a.previous() a == b a.equals(b)
a**b a.power(b)
a != b ! a.equals(b)
a|b a.or(b)
a <=> b a.compareTo(b)
a&b a.and(b)
a^b a.xor(b) a>b a.compareTo(b) > 0
~a a.negate() a >= b a.compareTo(b) >= 0
a[b] a.getAt(b) a<b a.compareTo(b) < 0
a[b] = c a.putAt(b, c)
a <= b a.compareTo(b) <= 0
28
Strings
• Single Quotes – java.lang.String
• Double Quotes – groovy.lang.GString – Allow
replacement of ${vars}
• Triple Single Quotes – Multi Line Strings, Newlines
always \n, Whitespace preserved.
• Triple Double Quotes – Multi Line GStrings
• Forward Slash – Escape backslashes ignored,
makes Regular Expressions more readable
29
String Example
me = 'Tarzan'
you = 'Jane'
line = "me ${me} - you $you"
assert line == 'me Tarzan - you Jane'
// Note abbrev dollar syntax $you
// Note == is equality not identity
date = new Date(0)
out = "Year $date.year Month $date.month Day $date.date"
assert out == 'Year 70 Month 0 Day 1'
out = "Date is ${date.toGMTString()} !"
assert out == 'Date is 1 Jan 1970 00:00:00 GMT !'
// Note $date.month access month property
30
String Example Continued
// Multi line
sql = """
SELECT FROM MyTable
WHERE Year = $date.year
"""
// Literal dollar sign
out = "my 0.02\$"
// Slashy Strings, don't need to escape
assert "abc" == /abc/
assert "\\d" == /\d/
31
Regular Expressions
• Find Operator: =~
Creates a matcher.
• Match Operator: ==~
Matches a regular expression.
• Pattern Operator: ~String
Creates a pattern from a string.
32
Regular Expression Example
// Find operator
assert "aaa1bbb2ccc3" =~ /bbb/
// Match operator – must match entire string
assert "aaa1bbb2ccc3" ==~ /(...\d)*/
// Patterns
def p = ~/a*b/
assert p instanceof Pattern
def m = p.matcher("aaaaab");
assert m.matches()
33
Ranges
• Specify an upper and lower bound of some
sequence.
• Can be used to replace:
if (a >= 0 && a <= upperBound) {
// do something with a
}
• Ranges are Objects
• lowerbound..upperbound: inclusive
• Lowerbound..<upperbound: half inclusive
• Supports Numbers, Strings, Dates, Reverse
Ranges.
• Can create your own, by overriding next(),
previous() and implements Comparable 34
Ranges Example
assert (0..10).contains(0)
assert (0..10).contains(5)
assert (0..10).contains(10)
assert (0..10).contains(-1) == false
assert (0..10).contains(11) == false
assert (0..<10).contains(9)
assert (0..<10).contains(10) == false
assert ('a'..'c').contains('b')
log = ''
// Replacement for Java for statements.
for (element in 5..9){
log += element
}
assert log == '56789'
35
Lists and Maps
• Groovy has language level support for maps
• Lists specified with [item, item, item] syntax
• java.util.ArrayList under the hood
• Maps specified with [name1:value, name2:value,
name3:value] syntax
• java.util.HashMap under the hood.
• Use [ ] operator to access.
• Define closures to ease iteration.
36
Lists - Specifying
myList = [1,2,3]
assert myList.size() == 3
assert myList[0] == 1
assert myList instanceof ArrayList
emptyList = []
assert emptyList.size() == 0
longList = (0..1000).toList()
assert longList[555] == 555
explicitList = new ArrayList()
explicitList.addAll(myList)
assert explicitList.size() == 3
explicitList[0] = 10
assert explicitList[0] == 10
37
Lists – Overloaded Subscript Operator
myList = ['a','b','c','d','e','f']
assert myList[0..2] == ['a','b','c'] // getAt(Range)
assert myList[0,2,4] == ['a','c','e'] // getAt(Index Collection)
// putAt(Range)
myList[0..2] = ['x','y','z']
assert myList == ['x','y','z','d','e','f']
myList[3..5] = []
assert myList == ['x','y','z']
myList[1..1] = ['y','1','2']
assert myList == ['x','y','1','2','z']
38
Lists – Negative Indexes
• Count from the back of the list. The last index is -1.
• Can be used with ranges.
• list[-3..-1] gives you the last three entries.
• list[1..-2] to cut away the first and the last entry.
39
Lists – Adding and Removing
myList = []
myList += 'a' // plus(Object)
assert myList == ['a']
myList += ['b','c'] // plus(Collection)
assert myList == ['a','b','c']
myList = []
myList << 'a' << 'b' // leftShift is like 'append'
assert myList == ['a','b']
assert myList - ['b'] == ['a'] // Minus to remove
40
Lists – GDK Methods
• Groovy Development Kit adds many methods to
the collection classes.
• Many take closures to perform some operation on
the collection
• Examples: min, max, sort, sum, collect, each, find,
unique etc…
41
Lists Iteration with Closures
def list = [1,2,3]
// Find even numbers
def even = list.find {item -> item % 2 == 0}
assert even == 2
// Is every number less than 5?
assert list.every { item -> item < 5}
// Is any number less than 2
assert list.any { item -> item < 2}
// Append each item to store
def store = ''
list.each { item -> store += item }
assert store == '123'
42
Maps - Specifying
def myMap = [a:1, b:2, c:3]
assert myMap instanceof HashMap
assert myMap.size() == 3
assert myMap['a'] == 1
def emptyMap = [:]
assert emptyMap.size() == 0
def explicitMap = new TreeMap()
explicitMap.putAll(myMap)
assert explicitMap['a'] == 1
43
Maps - Access
def myMap = [a:1, b:2, c:3]
// retrieve
assert myMap['a'] == 1
assert myMap.a == 1
assert myMap.get('a') == 1
assert myMap.d == null
assert myMap.get('d',0) == 0
assert myMap.d == 1 // now it's there
// assign
myMap['d'] = 1
assert myMap.d == 1
myMap.d = 2
assert myMap.d == 2
44
Maps - Iteration
def myMap = [a:1, b:2, c:3]
// Dump contents by each entry
myMap.each {entry ->
println "$entry.key = $entry.value"
}
// Dump contents by each key/value
myMap.each {key, value ->
println "$key = $value"
}
// Dump contents by for
for (key in myMap.keySet())
println "$key = " + myMap[key]
45
Closures
• A powerful and integral feature of Groovy. You won‟t
be able to avoid them.
• Essentially a block of code wrapped in an object.
• Similar to anonymous inner classes in Java but less
verbose and more flexible.
• Aka C# Delegate, Lisp Lambda, C function pointers.
• Useful for iteration, using resources safely.
• Avoids interface proliferation (Runnables, Observers,
Listeners, Visitors, Comparators, Strategies,
Commands, Controllers)
• Have access to local variables without having to
make them final as Java anonymous inner classes
require.
• Proposal from Gosling and others to add Closures
46 to
Closures - Specifying
def list = [1,2,3]
// Closure to print contents of a list
def closure = { x -> println x }
list.each(closure)
// Simplify 1 - Create closure within each
list.each({ x -> println x })
// Simplify 2 - () not required if closure last param
list.each { x -> println x }
// Simplify 3 - 'it' is default parameter name if one param
list.each { println it }
47
Closures - Calling
// Create a closure
def adder = { x, y -> return x + y }
// Call it using the call method
assert adder.call(2, 6) == 8
// Abbreviated call
assert adder(4, 3) == 7
// In a method
void adjustSalary(Closure adjustment) {
for(e in employees) {
adjustment(e)
}
}
48
Groovy Truth
Broader than Java which just uses Boolean tests to determine truth.
Boolean Corresponding boolean value is true
Matcher The matcher has a match
Collection The collection is non-empty
Map Whether the map is non-empty
String The string is non-empty
Number The number is non-zero
None of the above The object reference is non-null
49
Switch Statement
• An object that defines isCase method can be the candidate of a switch
statement.
• All of the standard Java classes have isCase defined.
Object a.equals(b)
Class a.isInstance(b)
Collection a.contains(b)
Range a.contains(b)
Pattern a.matcher(b.toString()).matches()
String (a==null && b==null) || a.equals(b)
Closure a.call(b)
50
Switch Statement Example
switch (10)
{
case 0 : assert false ; break
case 0..9 : assert false ; break
case [8,9,11] : assert false ; break
case Float : assert false ; break
case {it%3 == 0}: assert false ; break
case ~/../ : assert true ; break
default : assert false ; break
}
51
Looping
• Mostly the same as Java.
• Standard Java for not supported.
Use for(x in 0..9) instead
• Enhanced for loop, like Java 5 but uses in rather
than ':' and doesn't requires lists to be templated.
• In many cases, closures can be used instead.
52
Exceptions
• Mostly the same as java with the following
differences.
• Declaration of exceptions in method signatures is
optional. (Even for checked exceptions)
• You therefore don't have to catch checked
exceptions, they just go up the call stack
53
Classes
• Classes defined very much like in Java.
• Public by default
• Default visibility (not public, protected or private)
will automatically adds bean methods.
• Defining member variable type is optional
however can't stand alone.
• Fields can be referenced with subscript operator
myclass['myfield']
• Can also customize the field access operator '.' via
get / set overrides.
54
Class – Field Access
class Counter {
public count = 0
}
def counter = new Counter()
// Using field access operator
counter.count = 1
// using subscript operator
def fieldName = 'count'
counter[fieldName] = 2
55
Class – Overriding Field Access
class PretendFieldCounter {
public count = 0
Object get (String name) { return 'pretend value' }
void set (String name, Object value) { count++ }
}
def pretender = new PretendFieldCounter()
// Call get method via overridden '.' operator
assert pretender.isNoField == 'pretend value'
// Call set method via overriden '.' operator
pretender.isNoFieldEither = 'just to increase counter'
assert pretender.count == 1
56
Method Declaration
• Public by default
• void returns can be omitted
• Types in argument list can be omitted, Object
assumed.
• Dynamic dispatch used to resolve methods.
• Defaults allowed in argument list.
• Optionals parameters if last argument is Object[]
• Common practice to use Maps for 'named'
arguments.
57
Method Example
class Summer {
def sumWithDefaults(a, b, c=0) { return a + b + c }
def sumWithOptionals(a, b, Object[] optionals) {
return a + b + optionals.inject(0) { sum, i -> sum += i }
}
def sumNamed(Map args) {
['a','b','c'].each{ args.get( it, 0 ) }
return args.a + args.b + args.c
}
}
def summer = new Summer()
assert 2 == summer.sumWithDefaults(1,1)
assert 3 == summer.sumWithDefaults(1,1,1)
assert 2 == summer.sumWithOptionals(1,1)
assert 3 == summer.sumWithOptionals(1,1,1)
assert 2 == summer.sumNamed(a:1, b:1)
assert 1 == summer.sumNamed(c:1) 58
Safe Dereferencing
• The ?. operator can be used to safely dereference
member variables without worring about null
pointer exceptions.
• When the reference before that operator is a null
reference, the evaluation of the current expression
stops
def mapand null is returned.
= [a:[b:[c:1]]]
// Normal . operator
assert map.a.b.c == 1
// Safe dereferencing
assert map?.a?.x?.c == null
59
Constructors
• Public by default emp = new Employee()
emp = new Employee(name: 'Bob', age: 32)
• If implicit can class Employee {
def name
construct in 2 ways def age
}
• Empty constructor
• Named params emp = new Employee('Bob', 32)
emp2 = ['Joe', 41] as Employee
• If explicit can
Employee emp3 = ['Tom', 50]
construct in 3 ways class Employee {
Employee(name, age) {
this.name = name; this.age = age
• Traditional Java }
def name
• Using as keyword def age
}
• Implicit type
conversion
60
.groovy Files
• If a .groovy file contains no class, it becomes a
class of type Script using the filename as the class
name. main automatically added.
• If it contains exactly one class with same name as
file, then 1 to 1 relationship as in Java.
• Can contain multiple classes of any visibility
• Can mix scripting code and classes. No need to
worry about ordering. Classes can be referenced
before declared.
• Groovy classloader will search for .groovy files on
the classpath. Will only find classes where name
matches file.
61
Imports
• By default groovy
imports the following
packages into all .groovy
files
• import java.lang.*
• import java.util.*
• import java.io.*
• import java.net.*
• import groovy.lang.*
• import groovy.util.*
• import java.math.BigInteger
• import java.math.BigDecimal
• Import can be usedimport
for thirdparty.Element as
'type aliasing' usingElement2
as
keyword 62
Multimethods
• Groovy takes dynamic type of
arguments into account when
resolving methods. Java uses
static type.
def oracle(Object o) { return 'object' }
def oracle(String o) { return 'string' }
Object x = 1
Object y = 'foo'
assert 'object' == oracle(x)
assert 'string' == oracle(y) // would return 'object' in
Java
63
GroovyBeans
• Allows property access for all JavaBeans, defined
in Java or Groovy. (myclass.myproperty)
• Auto Generates get / set methods for properties
members in groovy classes if member variables
have default visibility.
• Also get / set only generated if you have not
already defined an accessor. This allows you to
create read only or write only properties.
64
GroovyBeans Example
class MyBean implements java.io.Serializable {
String foo, bar
// Make bar read only
String getBar() { return bar }
}
bean = new MyBean(foo: 'foo', bar: 'bar')
println bean.foo
bean.bar = 'error' // this won't be allowed
d = new Date()
println d.time // can access this as a property
65
GroovyBean Properties
• All properties in a bean can be accessed with
property semantics.
class SomeBean {
int var1
String var2
Date var3
}
def bean = new SomeBean(var1: 1, var2: "foo", var3: new
Date());
bean.properties.each { println it.key + " = " + it.value }
66
Spread Dot Operator
• '.*' use to access a property on each element in a
list. Person {
class
Person(def name) { this.name = name }
def name
}
def list = [new Person('Bob'), new Person('Tom'),
new Person('Sal')]
// Java approach
for(Iterator i = list.iterator(); i.hasNext();)
System.out.println(((Person) i).getName());
// Closure
println list.collect{ p -> p?.name }
// Spread dot operator
println list*.name
67
GPath
• GPath is a construction in Groovy code that powers
object navigation, analogous to XPath
• Builds upon bean properties, closures, safe
dereferencing operator and spread dot operator.
// Find all the 'get' methods in this class
println this.class.methods*.name.grep(~/get.*/).sort()
// Output
[getBinding, getClass, getMetaClass, getProperty]
68
GPath Example2
• Given the following model
class Invoice { List items; Date date }
class LineItem {
Product product; int count;
int total() {
return product.dollar * count
}
}
class Product { String name; def dollar}
69
GPath Example2
• You can perform GPath operations like the
following.
// get the totals of all line items in all invoices
invoices.items*.total()
// find all product names with a line item totals > 7000
invoices.items.grep{it.total() > 7000}.product.name
70
Other Topics
• Groovlets – Servlets in Groovy
• GSP – Groovy Server Pages
• Grails – Groovy's version of Ruby on Rails.
• Integrating Groovy – Add groovy macros into your
Java application.
• Lots more XML manipulation – XmlParser,
XmlSlurper
• jUnit support
• Windows / Com scripting via Scriptom
71
Question