Sunday, April 29, 2012

Hello Groovy

This is a quick exploration of how Groovy relates to Java.

Compiling and Running

Take a simple Java HelloWorld program, HelloWorld.java:


/**  
 * A Simple Hello World Program in Java
 */
public class HelloWorld {

  public static void main(String[] args) {
    String name;
    if(args.length > 0) { 
      name = args[0];
    } else {
      name = "World";
    }
    System.out.println("Hello, " + name);
  }
}
and confirm it compiles and executes in java:

Jupiter:src bendavies$ javac HelloWorld.java
Jupiter:src bendavies$ ls HelloWorld.class
HelloWorld.class

Jupiter:src bendavies$ java HelloWorld Ben
Hello, Ben


See that we can compile it and run it as is using Groovy:

Jupiter:src bendavies$ rm *.class
Jupiter:src bendavies$ groovyc HelloWorld.java
Jupiter:src bendavies$ groovy HelloWorld Ben
Hello, Ben


Groovyc is the Groovy compiler, which can compile both Groovy and Java source code.

If we change the file extension to 'groovy' we can run it directly without the compile step:

Jupiter:src bendavies$ cp HelloWorld.java Helloword.groovy
Jupiter:src bendavies$ groovy HelloWorld.groovy Ben
Hello, Ben

All without changing any Java code.

Simplifying the code

We've chosen an extremely simple example, but it still amounts to 8 lines of code. Groovy allows this code to be simplified dramatically. 

To start with, we do not need the surrounding class and main function - Groovy does something similiar for us automatically. This is now a groovy script. 

Try this by changing the HelloWorld.groovy file to  

String name;
if(args.length > 0) { 
  name = args[0];
else {
  name = "World";
}
System.out.println("Hello, " + name);

and run it again:

Jupiter:src bendavies$ groovy HelloWorld.groovy Ben
Hello, Ben


Groovy does not require semi-colons to separate statements on separate lines, nor does it require parenthesises around method parameters. Taking this into account:

String name
if(args.length > 0) { 
  name = args[0]
} else {
  name = "World"
}
System.out.println "Hello, " + name


Groovy automatically imports system APIs into the namespace and extends the String class to become a GString, which has many additional capabilities including support for inline variable evaluation. The last line can be changed to:

println "Hello, ${name}"


Groovy also has its additional methods of boolean evaluation (known as Groovy Truth). In particular List objects (which by default replace Array objects) whose length is zero evaluate to false. We can simplify our conditional and change:

if( args.length > 2 ) { .. }

to simply:

if( args ) { .. }

Famously, Groovy is a dynamically typed language. When we declare the variable name we do not need to type it - Groovy will detect and assign a data type at runtime. The 'def' keyword is used for untyped declarations:

def name
if(args) { 
  name = args[0]
} else {
  name = "World"
}
println "Hello, ${name}"


Using the ternary '?' operator we can actually move the entire conditional inside of the GString parameter to println. We can now write the entire Groovy HelloWorld example in a single line:

println "Hello, ${args?args[0]:'World'}"


Which is pretty neat. As you can tell Groovy strips back a lot of the unnecessary or mundane scaffolding required in Java with some solid assumptions and additional support that is a good fit for many applications.


Note that apart from a few edge cases any Java code can simply be renamed and treated as Groovy code. Groovy code can be called from Java and vice versa. 

No comments:

Post a Comment