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:
- Do not use any type (that will create a global variable):
a = 2
- Use keyword def (that will create a local variable):
def a = 2
- 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.groovya = 2
printf "%s - %s%n", a.getClass().getName(), a
a = "apple"
printf "%s - %s%n", a.getClass().getName(), a
Outputjava.lang.Integer - 2 java.lang.String - apple
Variables with no type are global so they can be accessed across methods.
src/NoTypeExample2.groovya = 2
void printVars() {
println a;
b = 3;
}
printVars();
print b;
Output2 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.groovydef a = 2
printf "%s - %s%n", a.getClass().getName(), a
a = "hi"
printf "%s - %s%n", a.getClass().getName(), a
Outputjava.lang.Integer - 2 java.lang.String - hi
Variables declared with def are local, so they cannot be accessed across methods:
src/DefExample2.groovydef a = 2
void printVars() {
println a;
}
printVars();
OutputCaught: 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.groovyint a = 2
println a
a = "apple"
println a
Output2 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.groovyint a = 2
void printVars() {
println a;
}
printVars();
OutputCaught: 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.groovyint 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()
Outputclass 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.groovydef 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
Outputnull 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)
Output4
src/MethodParamAndReturn2.groovy//using def
def sum(def x, def y) {
x + y;
}
println sum(1, 3)
Output4
src/MethodParamAndReturn3.groovy//using no types with parameters
def sum(x, y) {
x + y;
}
println sum(1, 3)
Output4
src/MethodParamAndReturn4.groovy//methods must return def or actual type
sum(x, y) {
x + y;
}
println sum(1, 3)
OutputCaught: 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 ProjectDependencies and Technologies Used: |