Groovy tries to be as natural as possible for Java developers. We’ve tried to follow the principle of least surprise when designing Groovy, particularly for developers learning Groovy who’ve come from a Java background.
Here we list all the major differences between Java and Groovy.
1. Default imports
All these packages and classes are imported by default, i.e. you do not have to use an explicit import
- java.io.*
- java.lang.*
- java.math.BigDecimal
- java.math.BigInteger
- java.net.*
- java.util.*
- groovy.lang.*
- groovy.util.*
2. Multi-methods
In Groovy, the methods which will be invoked are chosen at runtime. This is called runtime dispatch or multi-methods. It means that the method will be chosen based on the types of the arguments at runtime. In Java, this is the opposite: methods are chosen at compile time, based on the declared types.
The following code, written as Java code, can be compiled in both Java and Groovy, but it will behave differently:
In Java, you would have:
Whereas in Groovy:
That is because Java will use the static information type, which is that o
is declared as an Object
, whereas Groovy will choose at runtime, when the method is actually called. Since it is called with a String
, then the String
3. Array initializers
In Groovy, the { … }
You actually have to use:
4. Package scope visibility
In Groovy, omitting a modifier on a field doesn’t result in a package-private field like in Java:
Instead, it is used to create a property, that is to say a private field, an associated getter and an associated setter.
It is possible to create a package-private field by annotating it with @PackageScope
:
5. ARM blocks
ARM (Automatic Resource Management) block from Java 7 are not supported in Groovy. Instead, Groovy provides various methods relying on closures, which have the same effect while being more idiomatic. For example:
can be written like this:
or, if you want a version closer to Java:
6. Inner classes
The implementation of anonymous inner classes and nested classes follows the Java lead, but you should not take out the Java Language Spec and keep shaking the head about things that are different. The implementation done looks much like what we do for |
6.1. Static inner classes
Here’s an example of static inner class:
The usage of static inner classes is the best supported one. If you absolutely need an inner class, you should make it a static one.
6.2. Anonymous Inner Classes
6.3. Creating Instances of Non-Static Inner Classes
In Java you can do this:
Groovy doesn’t support the y.new X()
syntax. Instead, you have to write new X(y)
, like in the code below:
Caution though, Groovy supports calling methods with one parameter without giving an argument. The parameter will then have the value null. Basically the same rules apply to calling a constructor. There is a danger that you will write new X() instead of new X(this) for example. Since this might also be the regular way we have not yet found a good way to prevent this problem. |
7. Lambdas
Java 8 supports lambdas and method references:
Java 8 lambdas can be more or less considered as anonymous inner classes. Groovy doesn’t support that syntax, but has closures instead:
8. GStrings
As double-quoted string literals are interpreted as GString
values, Groovy may fail with compile error or produce subtly different code if a class with String
While typically, Groovy will auto-cast between GString
and String
if an API declares the type of a parameter, beware of Java APIs that accept an Object
9. String and Character literals
Singly-quoted literals in Groovy are used for String
, and double-quoted result in String
or GString
, depending whether there is interpolation in the literal.
Groovy will automatically cast a single-character String
to char
only when assigning to a variable of type char
. When calling methods with arguments of type char
Groovy supports two styles of casting and in the case of casting to char
10. Primitives and wrappers
Because Groovy uses Objects for everything, it autowraps references to primitives. Because of this, it does not follow Java’s behavior of widening taking priority over boxing. Here’s an example using int
This is the method that Java would call, since widening has precedence over unboxing. | |
This is the method Groovy actually calls, since all primitive references use their wrapper class. |
11. Behaviour of ==
In Java ==
means equality of primitive types or identity for objects. In Groovy ==
translates to a.compareTo(b)==0
, if they are Comparable
, and a.equals(b)
otherwise. To check for identity, there is is
. E.g. a.is(b)
.
12. Conversions
Java does automatic widening and narrowing conversions.
Table 1. Java Conversions
| Converts to | |||||||
Converts from | boolean | byte | short | char | int | long | float | double |
boolean | - | N | N | N | N | N | N | N |
byte | N | - | Y | C | Y | Y | Y | Y |
short | N | C | - | C | Y | Y | Y | Y |
char | N | C | C | - | Y | Y | Y | Y |
int | N | C | C | C | - | Y | T | Y |
long | N | C | C | C | C | - | T | T |
float | N | C | C | C | C | C | - | Y |
double | N | C | C | C | C | C | C | - |
*
Groovy expands greatly on this.
Table 2. Groovy Conversions
| Converts to | |||||||||||||||||
Converts from | boolean | Boolean | byte | Byte | short | Short | char | Character | int | Integer | long | Long | BigInteger | float | Float | double | Double | BigDecimal |
boolean | - | B | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N |
Boolean | B | - | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N |
byte | T | T | - | B | Y | Y | Y | D | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Byte | T | T | B | - | Y | Y | Y | D | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
short | T | T | D | D | - | B | Y | D | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Short | T | T | D | T | B | - | Y | D | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
char | T | T | Y | D | Y | D | - | D | Y | D | Y | D | D | Y | D | Y | D | D |
Character | T | T | D | D | D | D | D | - | D | D | D | D | D | D | D | D | D | D |
int | T | T | D | D | D | D | Y | D | - | B | Y | Y | Y | Y | Y | Y | Y | Y |
Integer | T | T | D | D | D | D | Y | D | B | - | Y | Y | Y | Y | Y | Y | Y | Y |
long | T | T | D | D | D | D | Y | D | D | D | - | B | Y | T | T | T | T | Y |
Long | T | T | D | D | D | T | Y | D | D | T | B | - | Y | T | T | T | T | Y |
BigInteger | T | T | D | D | D | D | D | D | D | D | D | D | - | D | D | D | D | T |
float | T | T | D | D | D | D | T | D | D | D | D | D | D | - | B | Y | Y | Y |
Float | T | T | D | T | D | T | T | D | D | T | D | T | D | B | - | Y | Y | Y |
double | T | T | D | D | D | D | T | D | D | D | D | D | D | D | D | - | B | Y |
Double | T | T | D | T | D | T | T | D | D | T | D | T | D | D | T | B | - | Y |
BigDecimal | T | T | D | D | D | D | D | D | D | D | D | D | D | T | D | T | D | - |
*
The truncation uses Groovy Truth when converting to boolean
/Boolean
. Converting from a number to a character casts the Number.intvalue()
to char
. Groovy constructs BigInteger
and BigDecimal
using Number.doubleValue()
when converting from a Float
or Double
, otherwise it constructs using toString()
. Other conversions have their behavior defined by java.lang.Number
.
13. Extra keywords
There are a few more keywords in Groovy than in Java. Don’t use them for variable names etc.
as
def
in
trait