构造函数中的自引用是否算作“转义"? [英] Does self-reference in the constructor counts as "escaping"?

查看:39
本文介绍了构造函数中的自引用是否算作“转义"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读有关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();
    }
}

  1. 首先,尽管父"显然是可变的,但子"是有效不变的",因为允许可变性的父二传手已经无法获得.
  2. 在构造函数中对"this"的引用对任何人都不可见(不是getter,也不会传递给任何其他对象).那么,这算作转义"吗?
  3. 但是该对象作为一个整体被一个最终字段(自身)引用,因此从理论上讲,它的整个内容应该被冻结".太太,最后一个字段本身是无法到达的,因此也许不算在内;我完全可以想象JIT会完全对其进行优化.
  4. 如果可以通过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 分配给异物的变量,这不会算作转义;
  • 除非类为 final ,否则
  • 调用属于 this 确实的公共的,可重写的方法就算是转义.因此,当您调用 setAnswer 时,您的代码会让 this 转义,而不是在将 this 分配给 self 时.为什么?因为子类可能会覆盖此方法并将 this 发布到任何外部代码.
  • 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 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.

关于您对 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆