/ GOOD PRACTICE

Immutable data structures in Java

Before being software developers, we are people - and thus creatures of habits. It’s hard for someone to change one’s own habits, it’s harder for someone to change someone else’s habits - and for some of us, it’s even harder.

This, week, during a code review, I stumbled upon this kind of structure:

public class MyStructure {

    private String myProp1;
    private String myProp2;
    // A bunch of other String properties

    public MyStructure(String myProp1, String myProp2 /* All other properties here */) {
        this.myProp1 = myProp1;
        this.myProp2 = myProp2;
        // All other properties set there
    }

    public String getMyProp1() { ... }
    public String getMyProp2() { ... }
    // All other getters

    public void setMyProp1(String myProp1) { ... }
    public void setMyProp2(String myProp2) { ... }
    // All other setters
}

Note: it seems like a JavaBean, but it’s not because there’s no no-argument constructor.

Looking at the code, I see that setters are never used in our code, making it a nice use-case for an immutable data structure - and saving a good number of lines of code:

public class MyStructure {

    private final String myProp1;
    private final String myProp2;
    // A bunch of other String properties

    public MyStructure(String myProp1, String myProp2 /* All other properties here */) {
        this.myProp1 = myProp1;
        this.myProp2 = myProp2;
        // All other properties set there
    }

    public String getMyProp1() { ... }
    public String getMyProp2() { ... }
    // All other getters
}

At this point, one realizes String are themselves immutable, which leads to the second proposal, which again save more lines of code:

public class MyStructure {

    public final String myProp1;
    public final String myProp2;
    // A bunch of other String properties

    public MyStructure(String myProp1, String myProp2 /* All other properties here */) {
        this.myProp1 = myProp1;
        this.myProp2 = myProp2;
        // All other properties set there
    }
}

Given that attributes are final and that Java String are immutable, the class still safe against unwanted changes. Note that it works only because String are immutable by definition in Java. With a Date property, it wouldn’t work as Date are mutable.

The same can be done with stateless services, with embedded services that needs to be accessed from children classes. There’s no need to have a getter:

public class MyService {

    // Can be accessed from children classes
    protected final EmbeddedService anotherService;

    public MyService(EmbeddedService anotherService) {
        this.anotherService = anotherService;
    }
}

Note this approach is 100% compatible with for Dependency Injection, either Spring or CDI.

Now, you cannot imagine the amount of back and forth comments this simple review caused. Why? Because even if that makes sense from a coding point of view, it’s completely different from what we usually do.

In that case, laziness and IDEs don’t serve us well. The latter make it too easy to create accessors. I’m pretty sure if we had to code getters and setters by hand, the above proposals would be more in favor.

This post could easily have been titled "Don’t let habits get the best of you". The lesson here is to regularly challenge how you code, even for simple easy stuff. There might be better alternatives after all.

Nicolas Fränkel

Nicolas Fränkel

Nicolas Fränkel is a Developer Advocate with 15+ years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). Usually working on Java/Java EE and Spring technologies, but with focused interests like Rich Internet Applications, Testing, CI/CD and DevOps. Currently working for Hazelcast. Also double as a teacher in universities and higher education schools, a trainer and triples as a book author.

Read More