Sunday, October 2, 2011

Final variables in groovy with dynamic constructors and @TupleConstructor

Up until groovy 1.8, it was not possible to declare variables in final as groovy when using the named constructor. Frequently with simple groovy objects, I would have a class that looks like this:

class Person {
String name
int age
}

It always bothered me that name and age could not be final. While I could declare an explicit constructor, such as

class Person {
final String name
final int age
public class Person(String name, int age) {
this.name = name
this.age = age
}
}

the explicit constructor is something the groovy helps eliminate the need for, and I always felt like it was a hassle to declare.

However, declaring variables final is generally recommended when you won't be modifying the variable, so I was torn. final ensures the variable is not set again when you didn't want it to be. When working with multiple threads, final fields guarantee visibility across threads when the object is constructed.

So in groovy 1.7, the options were to not make the variables final or to declare the explicit constructor.

Groovy 1.8 introduced the @TupleConstructor annotation. By annotating a class, another constructor is created that uses default values for all of the values.

@TupleConstructor
class Person {
final String name
final int age
}

So in this case, a constructor

Person(String name, int age)

is created.

Now both groovy and java classes can use this constructor, and the fields can be marked as final.

Note that the constructor fields are in the order the properties are declared, so be careful when reorganizing classes (and test, test and test some more).