zoukankan      html  css  js  c++  java
  • 隐式使用This 引用逸出

           发布(Publish)一个对象是指使对象能够在当前作用域之外的代码中被使用。例如将指向该对象的引用保存到其他代码可以访问到的地方 ,或者在一个非私有的方法中返回一个对象的引用或者将该引用传递到其他类的方法中。当发布一个对象时,在该对象的非私有域中的引用同样被发布出去,一般来说如果一个已经发布的对象能够通过非私有的变量和方法调用到其他的对象那么这个对象也被发布。

           逸出(Escape)是指 一个比应该被发布的对象被发布出去。

    在 《Java Concurrency in Practice》中关于隐式使用This 引用逸出的示例,比较难以理解如何逸出。ThisEscape发布EventListener时,也隐含地发布了ThisEscape实例本身,因为在这个内部类的实例中包含了对ThisEscape 实例的隐含引用。这个个人的理解代码是:

    /**
     *
     * @author zhangwei_david
     * @version $Id: ThisEscape.java, v 0.1 2014年11月3日 上午9:37:54 zhangwei_david Exp $
     */
    public class ThisEscape {
        private String name = null;
    
        public ThisEscape(EventSource source) {
            source.registerListener(new EventListener() {
    
                public void onEvent(Event event) {
                    doSomething(event);
                }
    
            });
            name = "TEST";
        }
    
        /**
         *
         * @param event
         */
        protected void doSomething(Event event) {
            System.out.println(name.toString());
        }
    }
    import java.awt.Event;
    
    /**
     * 
     * @author zhangwei_david
     * @version $Id: Listener.java, v 0.1 2014年11月3日 上午9:40:13 zhangwei_david Exp $
     */
    public interface EventListener {
        public void onEvent(Event event);
    
    }
    /**
     *
     * @author zhangwei_david
     * @version $Id: EventSource.java, v 0.1 2014年11月3日 上午9:38:40 zhangwei_david Exp $
     */
    public class EventSource {
    
        public void registerListener(EventListener listener) {
            listener.onEvent(null);
        }
    
    }
    /**
     *
     * @author zhangwei_david
     * @version $Id: Client.java, v 0.1 2014年11月3日 上午9:45:48 zhangwei_david Exp $
     */
    public class Client {
    
        /**
         *
         * @param args
         * @throws InterruptedException
         */
        public static void main(String[] args) throws InterruptedException {
            EventSource es = new EventSource();
            new ThisEscape(es);
    
        }
    
    }
    

     运行的结果是:

    Exception in thread "main" java.lang.NullPointerException
    	at com.cathy.demo.concurrency.escape.ThisEscape.doSomething(ThisEscape.java:33)
    	at com.cathy.demo.concurrency.escape.ThisEscape$1.onEvent(ThisEscape.java:21)
    	at com.cathy.demo.concurrency.escape.EventSource.registerListener(EventSource.java:15)
    	at com.cathy.demo.concurrency.escape.ThisEscape.<init>(ThisEscape.java:18)
    	at com.cathy.demo.concurrency.escape.Client.main(Client.java:21)
    

      这个就是由于在name 初始化之前,就使用了ThisEscape实例,而此时实例尚未完成初始化。

     同样修改SafeListener

    import java.awt.Event;
    
    /**
     *
     * @author zhangwei_david
     * @version $Id: SafeListener.java, v 0.1 2014年11月3日 上午10:20:26 zhangwei_david Exp $
     */
    public class SafeListener {
    
        private final EventListener listener;
        private String              name = null;
    
        private SafeListener() {
            listener = new EventListener() {
    
                public void onEvent(Event event) {
                    doSomething();
                }
            };
            name = "TEST";
        }
    
        public static SafeListener newInstance(EventSource eventSource) {
            SafeListener safeListener = new SafeListener();
            eventSource.registerListener(safeListener.listener);
            return safeListener;
        }
    
        /**
         *
         */
        protected void doSomething() {
            System.out.println(name.toString());
        }
    }
    /**
     *
     * @author zhangwei_david
     * @version $Id: Client.java, v 0.1 2014年11月3日 上午9:45:48 zhangwei_david Exp $
     */
    public class Client {
    
        /**
         *
         * @param args
         * @throws InterruptedException
         */
        public static void main(String[] args) throws InterruptedException {
            EventSource es = new EventSource();
            //        new ThisEscape(es);
            SafeListener.newInstance(es);
        }
    
    }
    

     结果是:

    TEST
    
  • 相关阅读:
    C#开发代码的小技巧1
    17. 装箱、拆箱的最小化
    Google Map开发(一) ASP.NET中调用Google Map API实现简单的地图显示
    C#可空类型
    C#如何扩展类型的内置方法
    Linq合并两个DataTable
    <br style="clear:both" /><br />
    GridView内容<br />换行
    数据库连接字符串大全
    JS将Table导出到Excel
  • 原文地址:https://www.cnblogs.com/wei-zw/p/8797821.html
Copyright © 2011-2022 走看看