iteye_15201 2011-03-07 13:56
浏览 241
已采纳

关于”隐式允许this引用逸出“

在《Java Concurrency in Practice》中,对于发布对象和数据逸出有两种示例,
其中之一是:
Listing 3.6. Allowing Internal Mutable State to Escape. Don't Do this.

class UnsafeStates {
private String[] states = new String[] {
"AK", "AL" ...
};
public String[] getStates() { return states; }
}


这个好理解;

另外一个示例是:
Listing 3.7. Implicitly Allowing the this Reference to Escape. Don't Do this.

public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}

作者认为“it implicitly publishes the enclosing ThisEscape instance as well, because inner class instances contain a hidden reference to the enclosing instance.”

作者的改进建议是:

If you are tempted to register an event listener or start a thread from a constructor, you can avoid the improper construction by using a private constructor and a public factory method, as shown in SafeListener in Listing 3.8.

Listing 3.8. Using a Factory Method to Prevent the this Reference from Escaping During Construction.
public class SafeListener {
private final EventListener listener;
private SafeListener() {
    listener = new EventListener() {
        public void onEvent(Event e) {
            doSomething(e);
        }
    };
}

public static SafeListener newInstance(EventSource source) {
    SafeListener safe = new SafeListener();
    source.registerListener(safe.listener);
    return safe;
}

}



作者对于错误的原因是这样解释的:
ThisEscape illustrates an important special case of escapewhen the this references escapes during construction. When the inner EventListener instance is published, so is the enclosing ThisEscape instance. But an object is in a predictable, consistent state only after its constructor returns, so publishing an object from within its constructor can publish an incompletely constructed object. This is true even if the publication is the last statement in the constructor. If the this reference escapes during construction, the object is considered not properly constructed.
有谁能把这个原因解释清楚点,即:为什么说这是一个未完成的对象呢,一旦内部匿名类那段代码执行完后,对象不就被注册了么?
  • 写回答

4条回答 默认 最新

  • springof 2011-03-07 13:56
    关注

    首先,在之前我并不知道或已对this引用逸出这回事没有够印象。
    在看查看资料后,说说个人的理解,如理解有误还请见谅。

    对this逸出代码作部分修改,易于理解。
    原文:
    [code="java"]
    public class ThisEscape {
    public ThisEscape(EventSource source) {
    source.registerListener(
    new EventListener() {
    public void onEvent(Event e) {
    doSomething(e);
    }
    });
    }
    }[/code]

    修改后。

    [code="java"]
    public class ThisEscape {
    public ThisEscape(EventSource source) {
    source.registerListener(
    new EventListener() {
    public void onEvent(Event e) {
    doSomething(e);
    }
    });
    a
    ....b;
    ....c;
    ....d;
    }
    }[/code]

    在构造ThisEscape对象时,代码执行到a处时对事件的注册已经完成,而此时构造函数并没有完成。
    如正是这个时刻,事件发生,那么在doSomething中this是可见的。
    那么就出现了this逸出的问题。

    再次声明,本人也不知道理解是否正确。仅做参考。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 运筹学排序问题中的在线排序
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决
  • ¥30 求一段fortran代码用IVF编译运行的结果
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 lammps拉伸应力应变曲线分析
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥15 请问Lammps做复合材料拉伸模拟,应力应变曲线问题