构造函数中的自引用是否算作“转义"? [英] Does self-reference in the constructor counts as "escaping"?
问题描述
阅读有关JSR-133的文章,它说:>
Reading this article about JSR-133, it says:
所有写入final字段(以及可到达的变量)间接地通过那些最后的字段)变成冻结",...
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.
我的问题是关于什么被认为是转义.更具体地说,我想知道这段代码(某种程度上是人为的和奇怪的)是否会导致可安全发布的Child对象:
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();
}
}
- 首先,尽管父"显然是可变的,但子"是有效不变的",因为允许可变性的父二传手已经无法获得.
- 在构造函数中对"this"的引用对任何人都不可见(不是getter,也不会传递给任何其他对象).那么,这算作转义"吗?
- 但是该对象作为一个整体被一个最终字段(自身)引用,因此从理论上讲,它的整个内容应该被冻结".太太,最后一个字段本身是无法到达的,因此也许不算在内;我完全可以想象JIT会完全对其进行优化.
- 如果可以通过getter访问"self",但是在构造函数中未调用getter,那么它是否算作转义(假设以前没有)?这会阻止JIT优化它,因此它必须然后计数",也许?
那么,Child是可以安全发布的"吗?如果不是,为什么?为什么自我"的吸气剂会改变答案?
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.
推荐答案
您 可能误解了转义的含义.关键是 this
的值不得到达构造函数以外的任何代码.我认为一些示例会更好地解释它:
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
分配给异物的变量,这不会算作转义; 除非类为 - 调用属于
this
确实的公共的,可重写的方法就算是转义.因此,当您调用setAnswer
时,您的代码会让this
转义,而不是在将this
分配给self
时.为什么?因为子类可能会覆盖此方法并将this
发布到任何外部代码.
final
,否则- setting a private field to
this
doesn't count as escaping; - calling a private method, which in turn doesn't call any further methods, and doesn't assign
this
to a foreign object's variable, doesn't count as escaping; - calling a public, overridable method belonging to
this
does count as escaping unless the class isfinal
. Therefore your code letsthis
escape when you callsetAnswer
, not when you assignthis
toself
. Why? Because a subclass may override this method and publishthis
to any foreign code.
关于您对 self
的推理的注释: self
可以从 this
获取,并且这不取决于外国呼叫者的事实无法获得其价值.一个方法可以在内部取消引用它就足够了.无论如何,关于冻结的规则没有考虑变量的访问级别.例如,一切都可以通过反射到达.
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.
这篇关于构造函数中的自引用是否算作“转义"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!