If a constructor of a class T
passes this
to as an argument to some method foo
, and foo
immediately performs a callback to the T
object (which has not yet finished executing its constructor), things might obviously go wrong, but what if I make sure that any fields accessed by foo
are initialized?
To make it clear what I am talking about, here is an example that does go wrong:
public class T {
// Class that accesses T, which could be defined somewhere outside
// rather than nested here.
static class FortyTwoChecker {
void foo(T t) {
System.out.println("Fourty-two is: "+t.get42());
}
}
// Fields set in constructor.
private final int fortyTwo;
// Callback method that accesses (and might also modify, in some other case)
// fields set in constructor.
int get42() { return fortyTwo; }
T(FortyTwoChecker checker) {
checker.foo(this); // goes wrong!
fortyTwo = 42;
}
}
When a T
object is constructed, Fourty-two is: 0
is printed, because foo
is called before fortyTwo
is set. But if I switch the two statements in T
’s constructor around, the output is Fourty-two is: 42
as expected. My question is: can I be sure that this kind of code always works as expected? That is, is it guaranteed that the compiler/VM does not mess with the sequential execution order, and that something does not bug out simply because there is a call to a method of an incompletely constructed object?
I expect that this may be difficult to answer if the callback is made from another thread, but can I at least be sure of it if everything happens in the same thread? This should be in the Java specification somewhere, but I cannot find it.
(Obviously, it would be nice to make sure that the callback is not made until the T
object is fully constructed – and not have to worry – but in the use case that made me think about this, that raises other problems.)