隐式this引用在构造函数中逸出----《Java并发编程实战》3.2

​​​​​​​​​​​​​​​​​​​​​这是《Java并发编程实战》3.2发布与逸出一节中的示例代码。我无法理解,this是怎么逸出的。

//隐式地使this引用逸出(不要这么做)
public class ThisEscape {
    public ThisEscape(EventSource source){
        source.registerListener(new EventListener() {
            public void onEvent(Event e){
                doSomething(e);
            }
        });
    }
}

书上说,当ThisEscape发布EventListener时,也隐含地发布了ThisEscape实例本身,因为在这个内部类的实例中包含了对ThisEscape实例的隐含引用。

前提:
内部类、匿名内部类都可以访问外部类的对象的域,为什么会这样,实际上是因为内部类构造的时候,会把外部类的对象this隐式的作为一个参数传递给内部类的构造方法,这个工作是编译器做的,他会给你内部类所有的构造方法添加这个参数,所以你例子里的匿名内部类在你构造ThisEscape时就把ThisEscape创建的对象隐式的传给匿名内部类了。

推论:
匿名内部类持有外部类的this引用后可能会调用外部类的实例方法(非私有方法,也不是final方法),这个时候当然是通过this引用调用的啦(代码中没有写this.doSomething(e),这是一种简写)。这个使用this引用指向的对象在还没有完全构造完就调用其实例方法改变属性,可能出现问题。比如外部类初始化的时候对一个int类型的参数赋值,然后doSomething(e)方法对该参数进行加1操作。如果onEvent()方法触发在外部类完成初始化之前怎么办?就会很尴尬。因为this引用提前被EventListener实例对象拿到。这个提前的拿到就是this引用的逸出
所以书上最后总结说,在构造函数中调用可改写的实例方法(不是私有方法,也不是final方法),同样会导致this引用在构造过程中逸出。还有构造函数中不能启动线程也是一样,即在没完成初始化时私自调用对象的方法,改变其状态,会存在隐患。
并且书中又说,解决方法是,在构造函数中注册一个事件监听器或者启动线程,可以使用一个私有的构造函数和一个公共的工厂方法(Factory Method),从而避免不正确的构造过程。如图
在这里插入图片描述
这样就使得注册监听在构造之后执行,保证onEvent()方法被调用在SafeListener的构造之后,对象正确初始化后再调用this引用指向的对象的方法修改属性就不是逸出,而是发布

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值