Changing Immutable Objects

Recently someone at work someone sent me a link to an article saying that getters and setters are evil by a guy named Yego256. He has a few other interesting posts about immutable objects here and here. They can be added to the list I made of pages about immutable objects here.

Hopefully Grails 3 will utilize immutability.

It takes a shift in mindset to start using immutable objects. Plus, in Java (and Groovy) a lot of web frameworks don’t utilize them, so people are not too familiar with them.

One issue some developers have is: Many things in the world are mutable. How can you make “changes” to immutable objects?

One answer is that you can use the values you don’t want to change to populate a new immutable object, and your variable/field name points to a new immutable object.

(If you can think of a better way to explain this, let me know. It’s kind of confusing to say that an immutable object is referenced by a “variable name”.)

I will demonstrate this with Groovy (using the annotations EqualsAndHashCode, Immutable and ToString). I made a class to model a state in the USA. States do not change their names, abbreviations or year they joined the union. But many of them have changed their capital cities. So we will make an object, and change its capital city while keeping everything else the same.

Here is our class:

Now let’s look at using it in a Groovy shell. The first capital of Illinois was a town called Kaskaskia, which no longer exists. Then it moved to Vandalia (which does still exist) and finally to Springfield.

I will try to change a few fields to prove the objects are immutable, and I will call hashCode() to show that we are dealing with different objects.

So we used the existing values to make new objects. The JVM used the same variable name (“il”) to refer to different immutable objects.

Here is the code without the output:

2015-06-06_14.23.56 update: I now realize that in order to prove the objects were truly different objects, I should have called System.identityHashCode(il) instead.

You’re welcome.