I saw Ken Kousen deliver his intro to Groovy talk today at the NY Java SIG. While I’ve done some small things with Groovy, I’ve forgotten a lot of what I once knew. Some of it, i remembered/used but am including here so this isn’t random facts but a summary of what was presented. Blogging about it this time in hopes I can retain more.
First of all, Ken is a great speaker. If you have the chance to see him in person, go. He:
- is entertaining – programmer humor
- presents info clearly
- has well thought out examples
- switches well between the groovy console, command line, browser and slides. While there were frequent switches, it was easy to follow
- live examples. Surprises and mistakes and all Icndb.com for humor in json examples provided energy towards the end
Useful links
- Groovy.codehaus.org – which has Groovy APIs, Groovy extensions to JDK APIs and the developer guide.
- Code examples from Making Java Groovy book
- Groovy console online (not talked about today, but I like it)
Now on to Groovy
What is groovy
- Groovy is like Java 3. Other jvm languages are simulating other languages like jythong or special purpose like functional languages. Groovy is a general purpose like a next generation OO language. Plus you can fall back to Java and make it “groovier” later [which is great for learning]
- Compiles to bytecode. Also a C compiler is available.
- If the name of your groovy file matches the name of the class, you can only have a class in the file. Otherwise you can put multiple classes or even just scripts in the file. Ken’s convention is to use underscores in filenames for scripts to identify them.
- Hello world is println “hi” [yes, that’s it]
- Parens are optional “until they are not”. They have a low precedence. Can leave out if obvious where they go
- Semicolons are always optional
- Perls goal is to write the shortest code possible. Groovy’s goal is to write the simplest code possible.
- Testing and build are the place to start with groovy when introducing into a reluctant organization
Options to run
- groovy foo.groovvy – don’t have to compile first. Should compile first when use it for real though. If want to integrate with java, must run groovyc to compile since java requires class files.
- The class files require groovy in the claspath to run with “java” rather than “groovy”. In groovy home, embedable directory contains groovy-all and groovy-allindy. The later is for invoke dynamic in Java
Tools
- Groovy Grails Tool Suite – for Eclipse
- Groovy menu has convert file extensions to groovy where right click java class. This lets you refactor slowly. [Or if create java class by accident like often do]
Operator overloading
- Every operator corresponds to a method. This means if your class implements that method, you can use that operator. This lets you write new Date() + 7 to get a date a week in the future.
- ** is power operator
- [] goes with getAt or putAt methods. This is what lets you say s[-1] or s[0..2] instead of pure array indexes. The getAt/putAt methods understand how to navigate. The methods also know to call next for 0..2 and prev for -3..-1. I also learned you can specify multiple ranges such as as s[0..2,4..5]
- In groovy == calls the equals method. Which means just converting a java class can result in an infinite recursion. Run your tests when refactoring
- To append: list << value
Groovy Types
- 123.getClass().getName() is an Integer. If you make it bigger becomes long or BigInteger dynamically.
- 2 – 1.1 uses BigDecimal so accurate unlike 2d – 1.1d which has Java roundoff error from using doubles.
- GString “test ${name}” uses interpolation to substitute the variable name. You don’t need braces if just one variable
- Single quotes are Java strings
- Double quotes are groovy strings
- Triple quotes are for multi line strings. Useful for SQL.
- Def means don’t know or care about type
- Duck typing. Can call any methods on def oject. If method exists at runtime ,call it. Else throw MissingMethodException at runtime.
- Map keys assumed to be Strings
Groovy translation
- S.class.name works. When it looks like you are referencing a private field, groovy adds get or set to call appropriate methods. The runtime environment provides getter and setter methods so you don’t need to write them
- Don’t need to type return belcause last expression is automatically returned
Plain Old Groovy Object (POGO)
Generates at runtime:
- getter/setter – If don’t want setter, add final to instance variable. If don’t want getter or setter on instance variable, type private.
- map based constructor
- class and methods public by default
- instance variables private by default
All you have to write is a class and the types. If you implement a method, Groovy will use yours and not generate it. If using the map based constructor, Groovy calls the default constructor and any appropriate setters. This means you don’t need overloaded constructors.
class Person{ String first String last } Person p = new Person() p.setFirst("f") println "$p.first" new Person(first: 'a', last: 'b')
Walkthru of converting a POJO to a POGO
- Remove getters and setters
- Remove private from instance variables
- Remove semicolons
- Remove constructor – need to use map constructor – affects callers [not backward compatible to simplify all the way]
- Remove public on class
- Remove import for java.util.Date
- Add @Canonical which includes @ToString, @TupleConstructor and @EqualsAndHashCode. All are AST transformations
- [1,2] creates list
- LinkedList a = [1] makes the desired type
- [1] as Set also creates the desired type
Closure
listOfStrings.each { /* code using it as default loop variable */ } map.each{ k,v -> /* code */ } list.collect{ /* transform to new list where results make up the new list */ }.join(',') // map reduce
Closure coercion can be used for an anonymouse inner class
{ /* code */} as FilenameFilter
Useful when an interface has only one method because uses implemetation for all methods in interfaces. Could pass a map of closures but might as well implement interface then.
Helpful classes/methods
- Groovy adds toURL to String class and getText to Url class masking query.toUrl().text a one liner
- XMLSlurper lets you get a dom tree from a URL which you can then navigate as tree.root.result[o].geometry.
location.lat - db.rows(“selet * from table”)
- db.eachrow(” query “){ /*code */}
- groovy.json.JsonSlurper().
parseText(json) - groovy.xml.MarkupBuilder to create. Similarly for xml, json and ant
- Must test code since constraints we are used to are gone
- Spock over GroovyTestCase – very nice framework. See example in github/book
Random interesting tips
- Can use map based constructor on a pojo too because groovy will call default constructor and set methods
- foo.with{} calls foo.xxx for any methods not found in scope
- Meta programming: add methods to class that need. Even to a java class. Complex.metaClass.plus= {}. Every class has a metaclass.
You forgot to mentioned that Ken is a Boston Red Sox fan 🙂
That’s right. And being a Red Sox fan is something to promptly bring up when bonding with a NY audience! 🙂