Close

Groovy - Data Type and Declaring Variables

[Last Updated: Dec 3, 2018]

Groovy supports all Java types (primitive and reference types).

All primitives types are auto converted to their wrapper types. So int a = 2 will become Integer a = 2.

When declaring variables we can do one of the followings:

  1. Do not use any type (that will create a global variable):
    a = 2
  2. Use keyword def (that will create a local variable):
    def a = 2
  3. Use the actual type (that will create a local variable of strict type Integer):
    int a = 3
    

Using no types for variables

When no type is used, variables act like they are of type Object, so they can be reassigned to different types:

src/NoTypeExample.groovy

a = 2
printf "%s - %s%n", a.getClass().getName(), a
a = "apple"
printf "%s - %s%n", a.getClass().getName(), a

Output

java.lang.Integer - 2
java.lang.String - apple

Variables with no type are global so they can be accessed across methods.

src/NoTypeExample2.groovy

a = 2

void printVars() {
    println a;
    b = 3;
}

printVars();
print b;

Output

2
3

The code outside methods but still in the script is copied to run method (tutorial), so during runtime everything is inside methods. In that sense, this feature allows the variables declared in a method to be accessible to other methods.

Groovy keeps these global variables in a map like object (groovy.lang.Binding).

Using def

When def is used, variables act like they are of type Object, so they can be reassigned to different types (same as when no type is used):

src/DefExample.groovy

def a = 2
printf "%s - %s%n", a.getClass().getName(), a
a = "hi"
printf "%s - %s%n", a.getClass().getName(), a

Output

java.lang.Integer - 2
java.lang.String - hi

Variables declared with def are local, so they cannot be accessed across methods:

src/DefExample2.groovy

def a = 2

void printVars() {
    println a;
}

printVars();

Output

Caught: groovy.lang.MissingPropertyException: No such property: a for class: DefExample2
groovy.lang.MissingPropertyException: No such property: a for class: DefExample2
at DefExample2.printVars(DefExample2.groovy:3)
at DefExample2.run(DefExample2.groovy:6)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

Using actual types (same as Java types)

They follow strict typing rules (just like Java). So they cannot be reassigned to different types:

src/ActualTypeExample.groovy

int a = 2
println a
a = "apple"
println a

Output

2
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'apple' with class 'java.lang.String' to class 'int'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'apple' with class 'java.lang.String' to class 'int'
at ActualTypeExample.run(ActualTypeExample.groovy:3)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

Like def variables they are also local, so they cannot be accessed across methods.

src/ActualTypeExample2.groovy

int a = 2

void printVars() {
    println a;
}

printVars();

Output

Caught: groovy.lang.MissingPropertyException: No such property: a for class: ActualTypeExample2
groovy.lang.MissingPropertyException: No such property: a for class: ActualTypeExample2
at ActualTypeExample2.printVars(ActualTypeExample2.groovy:3)
at ActualTypeExample2.run(ActualTypeExample2.groovy:6)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

It's usually better to use actual type with a variable, so as to help with documenting your code, and also help IDEs for code-completion, or for leveraging the static type checking or static compilation capabilities of Groovy.

Objects for everything

As seen above, Groovy uses Objects for everything (int is printed as java.lang.Integer). Primitives are auto converted to their wrapper type.

src/NoPrimitivesExample.groovy

int a = 2
printf("%s - %s%n", a.getClass(), a.getClass().isPrimitive())

def b = 2
printf "%s - %s%n", b.getClass(), b.getClass().isPrimitive()

c = 2
printf "%s - %s%n", c.getClass(), c.getClass().isPrimitive()

double d = 2.2
printf "%s - %s%n", d.getClass(), d.getClass().isPrimitive()

e = 2.3//no type
printf "%s - %s%n", e.getClass(), e.getClass().isPrimitive()

Output

class java.lang.Integer - false
class java.lang.Integer - false
class java.lang.Integer - false
class java.lang.Double - false
class java.math.BigDecimal - false

In Java it is not even possible to use Class.getClass() on primitives:

   //Java Code
   int a = 2;
   Class<?> c = a.getClass(); //error: Cannot resolve method 'getClass()'

Default values

In Groovy, all variables are initialized (even local) with their default values (just like instance variable).

src/DefaultValues.groovy

def a //initialized with null
println a

String s //initialized with null
println s

int b//initialized with 0
println b
println b + 3

boolean bool//initialized with false
println bool

Output

null
null
0
3
false

In Java, if we try to use a local variable without initializing:

   public static void main(String[] args) {
       int a;
       System.out.println(a); //error: variable a might not have been initialized
   }

Method parameters and return type

Regarding types, we have all three above options to use for method parameters, but return type must be the actual type or def:

src/MethodParamAndReturn.groovy

//using actual types
int sum(int x, int y) {
    x + y;
}

println sum(1, 3)


Output

4

src/MethodParamAndReturn2.groovy

//using def
def sum(def x, def y) {
    x + y;
}

println sum(1, 3)


Output

4

src/MethodParamAndReturn3.groovy

//using no types with parameters
def sum(x, y) {
    x + y;
}

println sum(1, 3)


Output

4

src/MethodParamAndReturn4.groovy

//methods must return def or actual type
sum(x, y) {
    x + y;
}

println sum(1, 3)


Output

Caught: groovy.lang.MissingPropertyException: No such property: x for class: MethodParamAndReturn4
groovy.lang.MissingPropertyException: No such property: x for class: MethodParamAndReturn4
at MethodParamAndReturn4.run(MethodParamAndReturn4.groovy:2)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

Example Project

Dependencies and Technologies Used:

  • Groovy 2.5.3
  • JDK 9.0.1
Data Type and Declaring Variables Select All Download
  • groovy-data-types-and-variables
    • src
      • NoTypeExample.groovy

    See Also