Reading this article about JSR-133, it says:
all of the writes to final fields (and to variables reachable indirectly through those final fields) become "frozen," ...
If an object's reference is not allowed to escape during construction, then once a constructor has completed and a thread publishes a reference to an object, that object's final fields are guaranteed to be visible ...
The one caveat with initialization safety is that the object's reference must not "escape" its constructor -- the constructor should not publish, directly or indirectly, a reference to the object being constructed.
My question is about what is considered escaping. More specifically, I want to know if this (somewhat artificial and strange) code results in a safely-publishable Child object:
class Parent {
/** NOT final. */
private int answer;
public int getAnswer() {
return answer;
}
public void setAnswer(final int _answer) {
answer = _answer;
}
}
public class Child extends Parent {
private final Object self;
public Child() {
super.setAnswer(42);
self = this;
}
@Override
public void setAnswer(final int _answer) {
throw new UnsupportedOperationException();
}
}
So, is Child "safely-publishable", and if not, why, and would a getter for "self" change the answer?
In case the purpose of the question isn't clear, I think that if this works, it would allow one to easily make a mutable class "safely-publishable", by just extending it as shown above.
You may be misunderstanding the meaning of escaping. The point is that the value of this
must not reach any code foreign to the constructor. I think a few examples would explain it better:
this
doesn't count as escaping;this
to a foreign object's variable, doesn't count as escaping;this
does count as escaping unless the class is final
. Therefore your code lets this
escape when you call setAnswer
, not when you assign this
to self
. Why? Because a subclass may override this method and publish this
to any foreign code.A note on your reasoning about self
: self
is reachable from this
and this doesn't depend on the fact that a foreign caller cannot get its value. It is enough that a method may internally dereference it. Anyway, the rules about freezing do not take into account the access level of variables. For example, everything is reachable via reflection.
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