【问题标题】:Java escaping reference to 'this'Java 转义对“this”的引用
【发布时间】:2017-06-18 11:05:39
【问题描述】:

我开始阅读Java Concurrency in Practice 并遇到了以下示例(这是一个负面示例 - 显示了不好的做法):

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

书中作者写道:

当 ThisEscape 发布 EventListener 时,它也会隐式发布封闭的 ThisEscape 实例,因为内部类实例包含对封闭实例的隐藏引用。

当我想到这些代码的用法时,我可以这样做:

EventSource eventSource = new EventSource();
ThisEscape thisEscape = new ThisEscape(eventSource);

并且我可以获得对注册的 EventListener 的引用,但是我可以获得对封闭的 ThisEscape 实例的引用是什么意思?

有人能给我举个这种行为的例子吗?用例是什么?

【问题讨论】:

  • 这可能是一个例子:stackoverflow.com/a/1084124/4563745
  • 好的,这是一个很好的用例,但我仍然不明白这种转义引用有什么问题——即使我会这样做 ThisEscape.this.doSomething();在匿名实现中,“this”仍然仅在 ThisEscape 中可见。
  • 事件源可以在 ThisEscape 构造函数完成之前发送事件。事件将在对象处于不可预测状态时进行处理。
  • 我为同一问题找到了另一个很好的解释:stackoverflow.com/questions/28676796/…

标签: java concurrency


【解决方案1】:

转义 this 引用的问题在于,其他线程中的代码可能会在构造函数完成构造对象之前开始与对象交互。

考虑这个例子:

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

        // Possible Thread Context switch

        // More important initialization
        foo = new Foo();
    }

    public void doSomething(Event e) {
        // Might throw NullPointerException, by being invoked
        // through the EventListener before foo is initialized
        foo.bar();
    }
}

【讨论】:

    猜你喜欢
    • 2013-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多