Thomas Skardal

Hello, computer.

Simplified value objects in Java

January 16, 2016

If you’ve ever taken a step out of your Java code you know that defining so called POJOs are quite cumbersome. Let’s say you’re defining a Item class. The item has a name and an optional description. You add the private variables, and it’s time for getters and setters. Also, you need a constructor. You should probably override a equals, hashCode and toString as well. Oh, and wait. The class should be immutable as well, so remove the setters again and make the fields final. Is it lunch time yet? :unamused:

There have been alternatives to this around for quite a while. Project Lombok is one and Immutables is another. I’ve tried out Lombok in a couple of side projects, so I wanted to take a look at Immutables. I don’t have an overview of all its features, but the essential feature is that you annotate an interface or an abstract class with @Immutable.Value and get a generated immutable class containing equals, hashcode and toString in addition to a builder that takes care of constructing valid objects.

@Value.Immutable
public interface Person {
    String name();
    Optional<String> description();
}

The definition above generates a builder that handles creation, copying, equality and everything you need for a Person type. If you need custom methods on your type you could define it as an abstract class instead. A lot less boilerplate, no doubt! If you can’t use a immutable value, you could check out Value.Modifiable which gives you a similar experience for more familiar JavaBean style classes.

Here’s some example usage of the above type definition:

Person p1 = ImmutablePerson.builder()
		.name("Test")
		.description("A test person")
		.build();
Person p2 = ImmutablePerson.builder()
		.name("Test")
		.description("A test person")
		.build();
Person p3 = ImmutablePerson.copyOf(p1).withName("Other");
System.out.println(p1.equals(p2)); // => true
System.out.println(p1.name()); // => Test
System.out.println(p3.name()); // => Other

I wanted to use gradle to build the example code. Immutables is based on annotation processing. Even though this is supported by javac IDEs need some configuration in order for it to pick up the generated code. I’ve used the [gradle apt plugin] to help me with this. With this build script I can run gradle eclipse and the APT-stuff is ready to use! :smiley:

plugins {
  id 'java'
  id 'eclipse'
  id "net.ltgt.apt" version "0.5"
}

sourceCompatibility = 1.8
version = 1.0

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.immutables:value:2.1.7'
    apt 'org.immutables:value:2.1.7'
}

For the record; this is how it would look like in Scala:

case class Item(name: String, description: Option[String] = None)