In the book Java Concurrency In Practice it explains the advantages of \"effectively immutable\" objects versus mutable objects concurrency-wise. But it does not explain what a
For circular immutables:
class Foo
{
final Object param;
final Foo other;
Foo(Object param, Foo other)
{
this.param = param;
this.other = other;
}
// create a pair of Foo's, A=this, B=other
Foo(Object paramA, Object paramB)
{
this.param = paramA;
this.other = new Foo(paramB, this);
}
Foo getOther(){ return other; }
}
// usage
Foo fooA = new Foo(paramA, paramB);
Foo fooB = fooA.getOther();
// publish fooA/fooB (unsafely)
A question is, since this
of fooA
is leaked inside constructor, is fooA
still a thread safe immutable? That is, if another thread reads fooB.getOther().param
, is it guaranteed to see paramA
? The answer is yes, since this
is not leaked to another thread before the freeze action; we can establish hb/dc/mc orders required by spec to prove that paramA
is the only visible value for the read.
Back to your original question. In practice there are always constraints beyond the pure technical ones. Initialize everything inside constructor is not necessarily the best option for a design, considering all engineering, operational, political and other human-ish reasons.
Ever wondering why we are fed to think that it is a great supreme idea?
The deeper problem is Java lacks a general cheap fense for safe publication which is cheaper than volatile. Java only has it for final
fields; for some reason, that fence is not available otherwise.
Now final
carries two independent meanings: 1st, that a final field must be assigned exactly once; 2nd, the memory semantics of safe publication. These two meanings have nothing to do with each other. It is quite confusing to bundle them together. When people need the 2nd meaning, they are forced to accept the 1st meaning too. When the 1st is very inconvenient to achieve in a design, people wonder what they have done wrong - not realizing that it's Java that did wrong.
Bundling of two meanings under one final
makes it double plus good, so that apparently we have more reason and motivation to use final
. The more sinister story is actually we are forced to use it because we are not given a more flexible choice.