Sunday, September 25, 2011

Groovy differences from Java (1/2 part)

What is Groovy all about?

Groovy is a dynamic programming language that's running on JVM (meaning that it is compiled to java byte-code and then it run on Java Virtual Machine).
Read here more about it features and also you can download it from same place.

When you unpack/install it, you can use groovy console for writing groovy scripts and to play with it. Console is located under : "$GROOVY_HOME/bin/groovyConsole".

Groovy essentially should provide more productivity compared to Java (and probably compared to other main stream OO languages) and it is damn good at it as it turn out...
Simple hello world in groovy (no main method or anything required).
println "Hello programmers!"

Basic differences

Note that almost all Java code is valid groovy code and you can mix & match java and groovy in your coding.
  • Firstly you get more default imports in groovy (java.io, java.math, java.util, java.net and groovy.lang and groovy.util). Reasons for this are obvious (70% of Java classes imports some of these packages).
  • Both null values and empty collections evaluates to false in groovy conditional statements. For example:
    Map map = new HashMap();
    // In Java you must do following for example:
    if (map != null && map.size() > 0) {
      ...
    }
    // In groovy this is enough:
    if (!map) {
      ...
    }
    
    Empty string also evaluates to false.
  • public is default class,fields,constant,methods visibility as compared to java package default visibility.
  • You don't have to catch checked exceptions as opposition to Java where compiler forces you to catch them. Is not catching these exception good practice? Well it makes code cleaner and also remove false security, but it really depends of your problem domain.

Silent helpers

There are couple of things that help you be more productive in groovy. They basically removes some of the non-necessary syntax from Java equivalents and replace it with smart defaults.
  • Semicolons who need them? In Groovy you by default do not need to type semicolons. But if you want to put more statements on one line, you still must separate them with semicolons.
  • Parentheses who need them? But you still need to use them. :) There are only couple of places you don't need them (println command for example or closures - more on closures on second part).
  • Return statement. You may be surprised, but you don't need to use return statement in non void methods. Groovy will return result from last expression evaluated. For example:
    private boolean something() {
        "a" == "b"
    }
    // Will return "false".
    
    But it is advisable to use return statement because of readability issues.

Properties (fields)

Groovy allows field access notation to Java bean properties (or fields whatever you like better). No need to define all that getters and setters for private fields, groovy all that handle behind the scenes. All you need to do to make this work is to leave default visibility on your fields (or properties) and you good to go. Examples:
Date date = new Date()
// You can access all Java beans properties
// using field name.
println date.time
// prints some long number...

class MyClass {
    
    // Default visibility for fields is private
    // but groovy generate setters and getters
    // behind scene.
    String firstName
    String lastName
    
    // Compiles without problem.   
    public static void access() {
        MyClass myClass = new MyClass()
        myClass.firstName = "John"
    }
    
}

Constructors

In Groovy you can instantiate bean using list of named arguments. This enables you to effectively treat maps as objects you can pass around and everything. For example:
// Here we create new SimpleDateFormat and setting default
// values to some of it properties.
SimpleDateFormat format = 
new SimpleDateFormat(lenient:false, numberFormat: "ddMMyyyy")

Added operations
Groovy introduced some new operations that do not exist in Java.
  • Null safe (?.) object navigation is basically null safe dot (.) operator. For example:
    // In Java if you have an object named "obj" that
    // encapsulate object named "field" you must do 
    // following to check if "field" is null:
    if (obj != null && obj.field != null) {
      ...
    }
    
    // In groovy U can use null safe operator
    // for same check and get same result:
    if (obj?.value != null) {
      ..
    }
    
    No more java.lang.NullPointerException! Great!
  • Elvis operator (?:) is basically shortened version of Java ternary (if-then-else) operator. It is called the ‘Elvis Operator’ due to its resemblance of Elvis’ trademark hair! :)
    For example:
    // When you use ternary operator in Java
    // U normally code something like this:
    Date date = (row.getDateFromDatabase() != null) ? 
                 row.getDateFromDatabase() : new Date();
    // In groovy U can get same result by using elvis:
    Date date = row.getDateFromDatabase ?: new Date()
    // It knows that you want to check for null values ;)
    
  • Spread-dot opeator (*.) operator calls a method on every item in collection. For example:
    // This will create new List wit all employees salaries.
    List employees = allEmployees*.getSalary()
    
    You don't need anymore to loop list only to extract single properties in another list. Great and Groovy stuff! :)
  • Comparisons with a spaceship (<=>) is used when you implement Comparable interface. In Java you must read API specification in order to properly implement int compare method (return negative is values i smaller, return positive if it is bigger or zero otherwise). Groovy makes our lives easier by providing operator that do exactly this:
    // This method will properly compare 
    // (in correspondence to Java API) two integers.
    public int compare(int number1, int number2) {
      return number1 <=> number2
    }
    
  • Equals (==) in Groovy equivalent of Java equals() method. It is null safe so it will work on null values (it will not throw NPE). Important to note is that if object implement Comparable interface, than it uses compareTo() method rather than equals.
    You can use is() method for identity if you are wondering.

Basic types in Groovy
In Groovy U can have access to all primitive Java types, but also you can use some Groovy specific type. Beside that you can also benefit from Groovy's syntactic sugar when working with basic types.
  • Numbers. Groovy threat primitive types as objects so you can call methods on them.
    // This is perfectly legal in Groovy
    222222.abs()
    // Although not so useful in this particular
    // example.
    
    Groovy uses BigDecimal for float-point calculations, it is maybe way slower than long and double, but it's removes quirks and quarks you have to deal with when working with float and double.
  • Strings. You can use Java Strings off course, but Groovy offers you several advantages over default Java String. The most important are embedded groovy expressions in the strings. Everything inside of ${} will be evaluated into string.
    int amount = 255
    Date today = new Date()
    
    String out = "Something, something, ${today} is amount: ${amount}"
    
    println out
    // This will print following:
    // Something, something, Sun Sep 25 18:34:52 CEST 2011 is amount: 255
    
    You don't need anymore to deal with clumsy Java concatenation. Which is good! :)

    Multiliners (""") are another Groovy extension to Java Strings. They allow you to easily create string literals that include line breaks.
    // So this is how you used to to this in Java.
    String bla1 = "Something, something,..." + "\n\n" +
    "              Another thing...."
    // Same code in groovy.
    String bla1 = """Something, something,...
    
                     Another thing...."""
    
    So no more + "\n" + stuff.
  • AS operator is very powerful. It is basically casting operator (like Java's (String)someObject). But is much more that that, it can cast Strings to Numbers (back and forth), List to Arrays (back and forth), Sets to Lists or Arrays(b & f) and not to forget String to Lists!(also b & f). For example:
    int number = ("12345" as int) - 1
    println number
    // 12344
    boolean isEqual = 123 as String == "123"
    // true
    println isEqual
    List abcList = "abc" as List
    println abc
    // [a, b, c]
    
    These are precisely things you would expect from script language and it is quite powerful stuff too.

Maps, lists and ranges
Groovy brings list and map concepts closer to it's type system.

  • Lists and Maps in Groovy have more natural feel than List and Maps in Java. Groovy uses comma-separated sequences of items between square brackets to define Lists or Maps. Let see it on example shall we:
    // In Java
    List cars1 = new ArrayList();
    cars1.add("Citroen");
    cars1.add("Audi");
    // [Citroen, Audi]
    
    // In groovy
    List cars2 = ["Citroen", "Audi"]
    // [Citroen, Audi]
    
    // Maps in groovy (you know Java part ;) )
    Map map1 = ["amount" : 15, "size" : 5]
    
    // Empty list
    List l = []
    // Empty map
    Map m = [:]
    
    // Get element from List
    String car = cars2[1]
    
    // Get element from Map
    String amount = map1["amount"]
    
    // Add item to list (somewhat different)
    cars2 << "Ferrari"
    // [Citroen, Audi, Ferrari]
    
    // Add item to map
    map1["mass"] = 55
    
  • Ranges are somewhat related to lists. Ranges are combination of lower and upper bound, which in the case of an integer range represents all numbers between two bounds for example.
    List computerComponents = ["Monitor", "CPU", "GPU", "Mem", "HDD"]
    // [Monitor, CPU, GPU, Mem, HDD]
    
    // Here you define only subset of previous list.
    List subComponents = computerComponents[1..2]
    // [CPU, GPU]
    
Regular expressions

Groovy provide support for regular expression at the language level. It provides new literals, new operators for regular expression matching, and a nice syntax for extracting groups. This is all you need to know about this because regular expression are topic for itself and it seem overkill to represent all complexity around then in this groovy article. For now we will say that groovy doesn't use backslash (as Java does) for regular expressions definition but rather forward slash. Also it introduce two new operators for matching:

=~ which match if pattern on the right side can be found in the string on the left side and ==! which match only strings that are exactly same as defined pattern.
Example:
println "999999" ==~ /\d+/
// true

println "mercury9" ==~ /\d+/
// false

println "mercury" ==~ /\w+/
// true
What is Groovy missing
Well not that much...
Character literals.
Java-like for loop in that you can't use "," operator.
Do...While.
Inner and anonymous classes, but it have closures (part 2 of this tutorial will deal with them) and together with ability to declare more than one class in Groovy file that is not so big deal.

No comments:

Post a Comment