封闭对象的引用通过匿名类java转义

我在实践中阅读Java并发性,下面的例子来自于此。 我的问题是这个参考逃脱是什么意思? 会有什么问题? 。 该引用如何从doSomething(e)中逃脱。

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 Escape { public Escape( Printer printer ){ printer.print(new Escaper(){ @Override public void parentData(){ theCulprit1(Escape.this); } public String name = "shal"; @Override public void theCulprit(){ System.out.println( this.name ); System.out.println( Escape.this.age ); } }); canAccess(); } public void canAccess(){ this.age = "25"; } public String age = "62"; @SuppressWarnings("unused") public static void main(String args[]){ Escape escape = new Escape(new Printer()); } } class Printer{ public void print(Escaper escaper){ escaper.theCulprit(); escaper.parentData(); } } class Escaper{ public void parentData(){ } public void theCulprit(){ } public void theCulprit1(Escape escape){ System.out.println(escape.age); } } 

由于逃逸物体的不完整构造,这输出了shal 62 62

我在哪里改变了我的代码

 public class Escape { private final Escaper escaper; private Escape( ){ escaper = new Escaper(){ @Override public void parentData(){ theCulprit1(Escape.this); } public String name = "shal"; public void theCulprit(){ System.out.println( name ); System.out.println( age ); } }; canAccess(); } public void canAccess(){ age = "25"; } public String age = "62"; public static Escape newInstance( Printer printer){ Escape escape = new Escape(); printer.print(escape.escaper); return escape; } @SuppressWarnings("unused") public static void main(String args[]){ Escape.newInstance(new Printer()); } } 

在这里。它输出shal 25 25

我对吗 ? 还有任何重新排序的操作,因为在第一个例子中,年龄被初始化为62.即使没有在我的第二个例子中使escaper字段最终它也有效!

在第一种forms中,事件侦听器对象被注册到构造函数中的事件源,因此它在构造函数完成之前使自己(以及通过关联“this”对象)可用于事件源。 如果内部类对象转义,则外部对象也会转义。

为什么这是个问题? 注册事件侦听器后,事件源可以随时调用其方法。 想象一下,事件源正在使用的线程开始调用事件侦听器方法。 现在甚至可以在构造函数完成之前发生这种情况。

然而,由于可见性问题,这个问题比它看起来更糟。 即使您将注册作为构造函数执行的“最后一个操作”,仍然可能会看到部分构造的对象或处于无效状态的对象。 在订购前没有适当的发生,根本没有可见性保证。

声明它最终会在订购之前发生(因此第二种forms)。

什么时候你有一个非静态的内部类,比如

 class Outer { class Inner { } } 

内部类有一个引用外部类的隐藏字段,所以你可以想象它就像这样

 class Outer { class Inner { Outer hiddenOuter; } } 

因此,无论使用内部对象,外部对象都是可引用的,因此它的生命周期至少与内部对象一样长。