参考我之前关于未完全构造的对象的问题,我还有第二个问题。正如 Jon Skeet 指出的那样,构造函数末尾有一个隐式内存屏障,可确保final
所有线程都可以看到字段。但是如果一个构造函数调用另一个构造函数呢?他们每个人的末尾是否有这样的内存屏障,或者仅在首先被调用的那个末尾?也就是说,当“错误”的解决方案是:
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;
}
}
以下是否也有效?
public class MyListener {
private final EventListener listener;
private MyListener() {
listener = new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
}
}
public MyListener(EventSource source) {
this();
source.register(listener);
}
}
更新:基本问题是this()
保证实际调用上面的私有构造函数(在这种情况下,预期的地方会有障碍,一切都是安全的),或者私有构造函数是否有可能作为一个内联到公共构造函数中优化以保存一个内存屏障(在这种情况下,直到公共构造函数结束时才会有屏障)?
规则是否在this()
某处精确定义?如果不是,那么我认为我们必须假设允许内联链式构造函数,并且可能一些 JVM 甚至可能javac
正在这样做。