在《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; }
}
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
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; }
}
首先,在之前我并不知道或已对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逸出的问题。
再次声明,本人也不知道理解是否正确。仅做参考。
楼上正解~
未完成的对象是指ThisEscape而不是EventListener。
主要是doSomething方法中可以使用this(但是ThisEscape没完成实例化),使用一个半成品的对像,肯定会出现与预期不一致的结果。
因为只有当构造函数返回时对象才处于可预测和一致的状态,当从构造函数发布对象时,只是发布类一个尚未完成的对象,哪怕发布对象的语句位于最后一行。虽然EventListener放在最后一行,使用到ThisEscape的字段,但是此时字段可能还没执行完成赋值