美文网首页spring boot
java 中的 this 逃逸

java 中的 this 逃逸

作者: 你可记得叫安可 | 来源:发表于2020-10-11 16:39 被阅读0次

    This 逃逸指的是对象还未构造完毕就对其进行了对外发布和使用。

    多线程或内部类引起的 this 逃逸

    这种错误的发生一般是因为在对象的构造函数中又构造了一个内部类,而内部类隐式地包含了 this 指针,并且内部类通过 this 指针隐式地使用了外部类中还未初始化的属性。

    public class ThisEscape {
        public ThisEscape(EventSource source) {
            source.registerListener(
                    new EventListener() {
                        public void onEvent(Event e) {
                            // 这里就可以使用未完全构造的 this 对象了
                            doSomething(e);
                        }
                    }
            );
        }
    }
    

    上面就是内部类引起的 this 逃逸。上面代码中的 onEvent 可能在 ThisEscape 构造函数调用完毕前就被回调,而此时 ThisEscape 还未被完全构造。
    如果想在构造函数中注册一个事件监听器或启动线程,那么可以使用一个私有的构造函数和一个公共的工厂方法,从而避免不正确的构造过程:

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

    因继承关系而导致的 this 逸出

    继承导致的 this 逸出
    如上所示,当我们在 non-final 类的构造方法中调用一个函数并传入 this 时,Android Studio 会提示我们 this 泄露。这是因为,MyLayout 类是 open 的,可能被子类继承,因此在调用 inflate 时,子类可能还没完成构造。inflate 方法可能会读取 this 中的一些属性,而这些属性可能还没有被初始化,从而导致不可预测的后果。

    事实上,即使 MyLayout 不是 open 的类,上面的用法一样会出现 this 逃逸的问题。因为已经将未构造完成的 this 传给了类外的 LayoutInflater.inflate 方法。不过,去掉 open 关键字,将 MyLayout 变为 final 类就不会出现上面的提示,我觉得应该是 Android Studiolint 检查没有适配这种场景。

    相关文章

      网友评论

        本文标题:java 中的 this 逃逸

        本文链接:https://www.haomeiwen.com/subject/kvjepktx.html