Itai Ganot Itai Ganot - 24 days ago 11
Groovy Question

Groovy: What's the difference between defining a variable without "def" versus using anchoring?

I'm learning Groovy now and I bumped into something that I don't understand and I hope you'd be able to shed some light.

In regard to the following example:

import groovy.transform.Field
@Field List awe = [1, 2, 3]
def awesum() { awe.sum() }
assert awesum() == 6


I understand that this anchoring allows me to change the scope of the awe variable from being run at the method level of the script to the class level of the script.

But then I think about the difference between defining a variables with def or without, example:

def var = "foo"


and

var = "foo"


As far as I understand the difference between the two examples is a difference of scope.
When I assign a value to a variable without a "def" or other type, in a Groovy script, it's added to the "binding", the global variables for the script.
Which means it can be accessed from all functions within the script.

So taking into consideration both "@Field" and defining a variable without using "def" and following that line of thought I've changed the example code to this:

import groovy.transform.Field
awe = [1, 2, 3]
def awesum() { awe.sum() }
assert awesum() == 6


And it works.

So my question is why use anchoring? if you can achieve the same goal by defining a variable without the "def"?

Answer

You do not achieve the same goal - see the difference below

import groovy.transform.Field
awe = [1, 2, 3]
def awesum() { awe.sum() }
assert awesum() == 6
awe = 1

work fine as the variable is dynamically typed. On contrary this fails

import groovy.transform.Field
@Field List awe = [1, 2, 3]
def awesum() { awe.sum() }
assert awesum() == 6
awe = 1

As the variable is strong typed (java.util.ArrayList)

Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '1' with class 'java.lang.Integer' to class 'java.util.List'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '1' with class 'java.lang.Integer' to class 'java.util.List'
        at FieldTest1.run(FieldTest1.groovy:5)