构造函数中的自引用是否算作"转义"?

Seb*_*iot 6 java constructor

阅读有关JSR-133的这篇文章,它说:

所有对最终字段的写入(以及通过这些最终字段间接到达的变量)都会变为"冻结",......

如果在构造期间不允许对象的引用转义,那么一旦构造函数完成并且线程发布对对象的引用,该对象的最终字段将保证可见...

初始化安全性的一个警告是,对象的引用不得"转义"其构造函数 - 构造函数不应直接或间接地发布对正在构造的对象的引用.

我的问题是关于什么被认为是逃避.更具体地说,我想知道这个(有点人为和​​奇怪的)代码是否会产生一个安全可发布的Child对象:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 首先,虽然Parent显然是可变的,但Child是"有效不可变的",因为允许可变性的父设置器不再可用.
  2. 构造函数中对"this"的引用对任何人都不可见(不是getter,也不会传递给任何其他对象).那么,这算是"逃避"吗?
  3. 但是整个对象被最终字段(自我)引用,因此理论上,它的整个内容应该被"冻结".OTOH,最终的领域本身是无法到达的,所以也许它不算数; 我完全可以想象JIT只是完全优化它.
  4. 如果通过getter可以访问"self",但是在构造函数中没有调用getter,那么它是否算作转义(假设之前没有)?这会阻止JIT优化它,所以它必须"计数",也许?

那么,儿童是"安全可发布的",如果没有,为什么,并且"自我"的吸气者会改变答案吗?

如果问题的目的不明确,我认为如果这有效,它将允许人们轻松地将一个可变类"安全地发布",只需如上所示扩展它.

Mar*_*nik 4

可能误解了逃避的含义。要点是 的值this不得到达构造函数之外的任何代码。我认为几个例子可以更好地解释它:

  • 将私有字段设置为this不算作转义;
  • 调用私有方法,该方法不会再调用任何其他方法,也不会分配this给外部对象的变量,不算作转义;
  • 调用属于 的公共的、可重写的方法this 确实算作转义,除非该类是final。因此,您的代码会this在您调用时进行转义setAnswer,而不是在您分配给时进行this转义self。为什么?因为子类可能会重写此方法并发布this到任何外部代码。

self关于您关于:的推理的注释self是可以访问的this,这并不取决于外国调用者无法获取其值的事实。一个方法可以在内部取消引用它就足够了。无论如何,关于冻结的规则没有考虑变量的访问级别。例如,一切都可以通过反射到达。