Effective Java with Groovy - Immutability

It would seem like mutability is the default design approach when it comes to Java. However, reading "Effective Java" makes you change your mind. The book suggests - 'minimise mutability'. Also, what is highly useful is the reason for favouring immutability - "immutability is simple". Did you get surprised?

Now, let's seek an answer to why many developers don't favour immutability. In Java, you have to write additional code to make objects immutable. You would start by making the fields final. This act would also imply that the fields cannot have setter methods. Hence you are only left with the constructors to initialise the fields. The challenge here is if your constructor has several arguments, its hard to remember the order of fields, especially when many of them share the same type.

Groovy reduces the cost of making objects immutable by providing higher-level constructs.

If you are new to Groovy, you might want to get a taste of Groovy from this post.

Consider the following code.

import groovy.transform.Immutable

@Immutable
class Rectangle {
    int length
    int breadth
}

Here I have applied the groovy.transform.Immutable AST transformation. This AST transformation will have the following influence on the compiler-generated class.

  1. The fields length and breadth are declared final (They are already private even without the @Immutable AST transformation.
  2. A constructor with both length and breadth as arguments gets created. Also, the compiler generates a constructor which takes a java.util.Map type as an argument so that you can instantiate the class with fewer fields and leave the rest with their default values.
  3. No setter methods get generated (they would have been present in the absence of Immutable AST transformation).
  4. Also equals and hashCode methods are generated for you, without explicitly specifying EqualsAndHashCode AST transformation.
  5. toString method is implemented for you.

Let's create an instance of the class as follows.

Rectangle rectangle = new Rectangle(breadth: 10, length: 20)
println rectangle // Rectangle(20, 10)

Thus Groovy solves reduces the barrier to favour immutability in the following ways.

  1. No boilerplate code. All you have to do is apply the Immutable AST transformation on the class.
  2. You don't need to remember the order or fields to invoke the constructor. Instead, make use of the map constructor.

If you are interested in learning more about how Effective Java applies to Groovy code, you may want to take a look at my GR8Conf EU presentation.

References:

Show Comments