Groovy annotations

As I wrote in my last post Groovy 1.8 is still in progress. One of the new features I liked a lot is annotation support for AST transformations (i.e. @ToString, @Canonical etc.).

As I'm still acquainted with Groovy, I've decided to look what useful annotations it has already. So this post is about what was found.

There are next annotations in the groovy.lang package:

  • @Lazy
  • @Immutable
  • @Newify
  • @Singleton
  • @Mixin
  • @Category

Also want to describe them with few simple samples.

@Lazy

This annotation can be applied to class field. As result new instance for field value is created on get method call for field property. In this case Groovy generates getter method for you, that checks whether field is not initialized yet and initialize it in this case, otherwise returns its value:

@Lazy T x

generates next code:

private T $x

T getX() {
if ($x != null)
return $x
else {
$x = new T()
return $x
}
}

You also can do lazy field initialization with specified value, just assign this value for field with @Lazy annotation:

@Lazy T x = new T(code: 'S')

That will generate next code:

private T $x

T getX() {
T $x_local = $x
if ($x_local != null)
return $x_local
else {
synchronized(this) {
if ($x == null) {
$x = new T(code: 'S')
}
return $x
}
}
}

Absolutely useful thing with only a few of keypresses. That's awesome.

Read more in GroovyDoc

@Immutable

Used to mark classes and make them immutable. That's mean that your class becomes final and nobody can change value field value and you get tuple and map based constructors. Also Groovy generated toString(), hashCode() and equals() methods for you. You should also need to be sure that fields types are immutable, primitives, strings, enums or are annotated with @Immutable.

Read more in GroovyDoc

@Newify

This annotation is perfect for DSL expressions. With it you can change creating new objects expression, for example, use

def b = Book('The Best Book Ever')

instead of

def b = new Book('The Best Book Ever')

Read more in GroovyDoc

@Singleton

Well, another annotation that makes your life easier. As you maybe already understand, this annotation is for types and make them singletons.
getInstance() method is generated for you, so simply call it when you need new instance. If you set annotation lazy parameter to be true, your singleton instance will be created on first call to this method. As for this case method supports double checking locks, you may be sure that only one instance will be created. Here is some sample:

@Singleton
class Player {
def play() {}
def stop() {}
}

...

Player.instance.start()

Read more in GroovyDoc and Singleton transformation.

@Mixin

Used to mix one or few types into annotated type. As result, you can have a class that have members (fields and methods) from other classes, specified in the annotation. And here is sample:

class Book {
String name
String author

def find(text) {
....
}
}

@Mixing(Book)
class HardBookMetadata extends Metadata {
int pages
String publication
}

....
def metadata = new HardBookMetadata()
metadata.title = 'Some cool title'
metadata.author = 'Ruslan Khmelyuk'
metadata.pages = 400

println metadata.find('cool')

As you see, using variable metadata of HardBookMetadata type have access to Book members.
Yeah, this also can be used with @Category.

Read more in GroovyDoc.

No comments: