发布与逸出

182 阅读1分钟

发布与逸出

发布(publish)一个对象的意思是指,是对象能够在当前作用域之外的代码中使用。例如,将一个指向该对象的引用保存到其他代码可以访问到的地方,或者在某一个非私有的方法中返回该对象的引用,或者将引用传递到其他类的方法中。

在许多情况下,我们要确保对象及其内部状态不被发出。而在某些情况下,我们又需要发布某个对象,但如果在发布时要确保线程安全性,则可能需要同步。发布内部状态可能会破坏封装性,并使得程序难以维持不变性条件。例如,如果在对象构造完成之前就发布该对象,就会破坏线程安全性。当某个不应该发布的对象被发布时,这种情况情况被称为逸出(Escape)

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

    void doSomething(Event e) {
    }


    interface EventSource {
        void registerListener(EventListener e);
    }

    interface EventListener {
        void onEvent(Event e);
    }

    interface Event {
    }
}

该代码可能在ThisEscape对象初始化未完成时触发事件监听,调用doSomething(),如果doSomething()方法内返回ThisEscape的状态,有可能返回一个错误的状态。

不要在构造过程中使用this引用逸出

正确实例

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;
    }
}