The Road from Java to Groovy

About Me

1st Career

About Me

2nd Career

OCI Grails Team

Legend

Cruisin' to easy migration and interop

Caution for potholes & speed bumps

Stopping for rework or collisions

Legend

Anywhere you see a parrot means this inconsistency with Java will be changing when the new "parrot" grammar changes are available in Groovy 3.0 and maybe as options in 2.5.x  

  • Generally, migration is very easy
  • Often, just renaming the file works
  • There are a few roadblocks and detours

Java to Groovy Migration

  • Classes
  • Interfaces
  • Inheritance
  • Enums

Groovy OOP like Java

  • Kind of like Java 8 interfaces
  • Kind of like classes
  • Can have state and behavior

Groovy also has traits

trait Singer {
    int songLength

    void sing() {
        println "Oh say can you see..."
    }
}

class Teacher implements Singer { }

class Student implements Singer {
    void sing() {
        println "Twinkle twinkle little star..."
    }
}

Example: An Order class (Java)

Example: An Order class (Java)

Example: An Order class (Java)

Example: AN Order class (Groovy)

The leftShift method implements << operator overload

AST transformations are compile time

@Canonical

  • Uber AST that wraps three other ASTs
    • @TupleConstructor
    • @EqualsAndHashCode
    • @ToString
  • If you also include one of those, it takes precedence

Example: A Line Item class (JAVA)

Example: A Line Item class (JAVA)

Example: A Line Item class (JAVA)

Example: A Line Item class (Groovy)

return is optional

result of last statement is returned

Example: Taxable Interface (Java)

Note: Groovy Taxable interface is nearly identical

Example: Order App (Java)

Example: Order App (Java)

Example: Order App (Java)

Example: Order App (Groovy)

Example: Order App (Groovy)

The Order's leftShift method receives the LineItem

Example: Order App (Groovy)

Triple quotes allow us to easily create formatted, multiline strings

Example: Order Service (Java)

Java 8 introduced streams, method references and lambdas

Groovy doesn't support lambdas and Java method references

Example: Order Service (Java)

Java 8 Gaps in Groovy

  • Java 8 introduced major language changes around functional programming
  • Functional interfaces with default methods
  • Lambda expressions: (a,b) -> a + b
  • Method references: BigDecimal::add
  • Groovy already had functional idioms
  • Does not support lambdas and method references directly

Detouring Around The Java 8 Gaps

  • Java 8 method references are a kind of shorthand for lambdas
  • Lambdas implement functional interfaces
  • Groovy closures can be coerced into meeting contract of the functional interface
  • Wherever you find a Java 8 method reference or lambda, you can replace it with a closure

Example: Order Service (Groovy)

Example: Results

Mostly Smooth running in Regards

to Migration and Interoperability

  • Often can simply rename file to .groovy
  • Use closures to work around Java 8 gaps
  • AST transformations are at compile time, so support interop with Java

Method Dispatching Differences (JAVA)

Method Dispatching Differences (Groovy)

Groovy Equality

== uses compareTo if Comparable, else equals()

<=> 'spaceship' operator

How are two Codes equal?

Groovy Equality

AST transformations happen at compile-time

"spaceship" operator is compareTo

Groovy Equality

Codes equal via compareTo == 0

Groovy Equality

a.is(b)

a === b

Groovy Strings

Can be written as map['Jack']

Groovy Strings

Groovy Strings

Map map = ["${name}" : 57]; println map; println map.Jack

Groovy Truth

Groovy Truth

Groovy Truth

asBoolean defines Groovy truth for the object

Groovy Truth

Groovy Truth

Performance (JAVA)

Groovy Dynamic Method Dispatch

Cruising Performance (Groovy)

@CompileStatic bypasses Groovy MOP

Note Groovy method pointers

Missing Pavement

Do / While (Java)

Do While (Java)

Do / While (Groovy)

Groovy has never supported do/while

To Groovy, do { } looks like do(Closure)

until then...

Do While (Groovy)

Note @CompileStatic

Do While (Groovy)

Types (Java)

Types (Java)

Types (Groovy)

All types in Groovy are Objects

Keyword Collisons

Automatic Resource

Management (ARM) Blocks

Path file = Paths.get("/path/to/file");
Charset charset = Charset.forName("UTF-8");
try (BufferedReader reader = Files.newBufferedReader(file, charset)) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }

} catch (IOException e) {
    e.printStackTrace();
}
  • ARM blocks introduced in Java 7
  • Goal was to make it easier to ensure resources cleaned up

code from http://groovy-lang.org/differences.html

Groovy Doesn't support Automatic Resource Management (ARM) Blocks

new File('/path/to/file').eachLine('UTF-8') {
   println it
}

// or this
new File('/path/to/file').withReader('UTF-8') { reader ->
   reader.eachLine {
       println it
   }
}
  • Groovy idioms for doing the same thing are even easier
  • Meets goal of making it easy to clean up resources

code from http://groovy-lang.org/differences.html

Summary

Migration from Java and interop with Java is almost trivial

There are a few issues arising from the differences between Groovy and Java, but these are easy to remedy

Very few issues are irreconcilable, such as keyword conflicts.

Resources

Thank you!

NFJS - Road from Java to Groovy

By Jack Frosch

NFJS - Road from Java to Groovy

  • 4,200