Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do fields need to be explicitly final to have a "proper" immutable object?

You often read about immutable objects requiring final fields to be immutable in Java. Is this in fact the case, or is it simply enough to have no public mutability and not actually mutate the state?

For example, if you have an immutable object built by the builder pattern, you could do it by having the builder assign the individual fields as it builds, or having the builder hold the fields itself and ultimately return the immutable object by passing the values to its (private) constructor.

Having the fields final has the obvious advantage of preventing implementation errors (such as allowing code to retain a reference to the builder and "building" the object multiple times while in fact mutating an existing object), but having the Builder store its data inside the object as it is built would seem to be DRYer.

So the question is: Assuming the Builder does not leak the Object early and stops itself from modifying the object once built (say by setting its reference to the object as null) is there actually anything gained (such as improved thread safety) in the "immutability" of the object if the object's fields were made final instead?

like image 628
Yishai Avatar asked May 17 '10 22:05

Yishai


2 Answers

Yes, you do get "thread safety" from final fields. That is, the value assigned to a final field during construction is guaranteed to be visible to all threads. The other alternative for thread safety is to declare the fields volatile, but then you are incurring a high overhead with every read… and confusing anyone who looks at your class and wonders why the fields of this "immutable" class are marked "volatile."

Marking the fields final is the most correct technically, and conveys your intent most clearly. Unfortunately, it does make the builder pattern very cumbersome. I think it should be possible to create an annotation processor to synthesize a builder for an immutable class, much like Project Lombok does with setters and getters. The real work would be the IDE support needed so that you could code against the builders that don't really exist.

like image 126
erickson Avatar answered Sep 19 '22 06:09

erickson


An Object can certainly have mutable private fields and still work as an immutable object. All that matters to meet the contract of immutability is that the object appears immutable from the outside. An object with non-final private fields but no setters would for example satisfy this requirement.

In fact, if your encapsulation is right then you can actually mutate the internal state and still operate successfully as an "immutable" object. An example might be some sort of lazy evaluation or caching of data structures.

Clojure for example does this in its internal implementation of lazy sequences, these objects behave as if they are immutable but only actually calculate and store future values when they are directly requested. Any subsequent request retrieves the stored value.

However - I would add as a caveat that the number of places where you would actually want to mutate the internals of an immutable object are probably quite rare. If in doubt, make them final.

like image 40
mikera Avatar answered Sep 22 '22 06:09

mikera