Must immutable objects have all properties be final
?
According to me not. But I don't know, whether I am right.
In Java, we know that String objects are immutable means we can't change anything to the existing String objects. final means that you can't change the object's reference to point to another reference or another object, but you can still mutate its state (using setter methods e.g).
An object (class or instance) is immutable, if its internal state cannot be changed (reflection doesn't count). Making a field final guarantees only that the value (if it's a primitive) or reference (for non-primitives) cannot be changed.
An immutable object is an object whose internal state remains constant after it has been entirely created. This means that the public API of an immutable object guarantees us that it will behave in the same way during its whole lifetime.
The string is immutable means that we cannot change the object itself, but we can change the reference to the object. The string is made final to not allow others to extend it and destroy its immutability.
The main difference between an immutable object (all properties final) and an effectively immutable object (properties aren't final but can't be changed) is safe publication.
You can safely publish an immutable object in a multi threaded context without having to worry about adding synchronization, thanks to the guarantees provided by the Java Memory Model for final fields:
final fields also allow programmers to implement thread-safe immutable objects without synchronization. A thread-safe immutable object is seen as immutable by all threads, even if a data race is used to pass references to the immutable object between threads. This can provide safety guarantees against misuse of an immutable class by incorrect or malicious code. final fields must be used correctly to provide a guarantee of immutability.
As a side note, it also enables to enforce immutability (if you try to mutate those fields in a future version of your class because you have forgotten it should be immutable, it won't compile).
Clarifications
final List
, no mutating operations (add, remove...) must be done after construction) and (ii) you don't let this
escape during constructionExample of unsafe publication:
class EffectivelyImmutable { static EffectivelyImmutable unsafe; private int i; public EffectivelyImmutable (int i) { this.i = i; } public int get() { return i; } } // in some thread EffectivelyImmutable.unsafe = new EffectivelyImmutable(1); //in some other thread if (EffectivelyImmutable.unsafe != null && EffectivelyImmutable.unsafe.get() != 1) System.out.println("What???");
This program could in theory print What???
. If i
were final, that would not be a legal outcome.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With