Java 内部类如何使这个引用转义

Java 内部类如何使这个引用转义,java,concurrency,Java,Concurrency,不遵从代码示例 似乎在内部类中没有调用实例方法,所以我不知道这个引用是如何在这个代码段中转义的 我读过一些问题,比如,但它是不同的 公共类DefaultExceptionReporter实现ExceptionReporter{ 公共默认例外报告程序(例外报告程序){ er.setExceptionReporter(新的ExceptionReporter(){ 公开作废报告(可丢弃的t){ //报告例外情况 } 公共无效集合例外报告程序(例外报告程序){ //注册例外报告程序 } }); } //

不遵从代码示例

似乎在内部类中没有调用实例方法,所以我不知道这个引用是如何在这个代码段中转义的

我读过一些问题,比如,但它是不同的

公共类DefaultExceptionReporter实现ExceptionReporter{
公共默认例外报告程序(例外报告程序){
er.setExceptionReporter(新的ExceptionReporter(){
公开作废报告(可丢弃的t){
//报告例外情况
}
公共无效集合例外报告程序(例外报告程序){
//注册例外报告程序
}
});
}
//setExceptionReporter()和report()的默认实现
}

之所以会发生这种情况,是因为当
DefaultExceptionReporter
发布匿名类时,它也隐式发布封闭的
DefaultExceptionReporter
实例。您可以通过编写一个简单的程序来实际访问该实例来检查这一点:

public static void main(String[] args) {
    ExceptionReporter rep = new DefaultExceptionReporter(new ExceptionReporter() {
        @Override
        public void setExceptionReporter(ExceptionReporter er) {
            for (Field field : er.getClass().getDeclaredFields()) {
                System.out.println(field);
            }
        }

        @Override
        public void report() { }
    });
}
输出:

final my.package.DefaultExceptionReporter my.package.DefaultExceptionReporter$1.this$0

这是因为匿名类始终是一个非静态的内部类(),并且这类类始终具有对封闭类的隐式引用。

DefaultExceptionReporter
的构造函数中,您实例化了一个匿名类。匿名类在父类完全实例化之前获取对其父类的引用

如果父对象具有state,这意味着匿名类理论上可以在完全构造之前对其进行操作

希望这能说明潜在的问题:

class DefaultExceptionReporter implements ExceptionReporter {

    private final int foo;

    public DefaultExceptionReporter(ExceptionReporter er) {
        er.setExceptionReporter(new ExceptionReporter() {

            {
                System.out.println(DefaultExceptionReporter.this.foo);
            }

            public void report(Throwable t) {}
            public void setExceptionReporter(ExceptionReporter er) {}
        });
        foo = 1;
    }

    // ...
}
这将打印零,即使
foo
为最终值并指定为1。最后一个变量有两个通常不可能的值


因为你的对象是无状态的,我认为这没什么大不了的。但是,您可能应该将类声明为
final
,因此不可能扩展它并添加状态。

在本例中,技术上允许
引用转义

让我们想象一下:

  • 其他一些线程可以访问传递给
    DefaultExceptionReporter的构造函数的
    ExceptionReporter
    实例
  • 实际上,您可以通过
    DefaultExceptionReporter访问外部实例。这是匿名类实例的
    in-methods”(例如,您希望访问字段或调用方法)
在这种情况下,其他线程可能会调用传递给
DefaultExceptionReporter
的构造函数的
ExceptionReporter
上的方法。如果这些方法调用通过
setExceptionReporter
设置的实例中的方法,则其他线程可能会访问
DefaultExceptionReporter
在其实例完全创建之前。从其他
线程
的访问可以通过引用链完成:


ExceptionReporter
(传递给构造函数)->
ExceptionReporter
(匿名)->
DefaultExceptionReporter。这

意味着外部类实例是否引用转义,取决于内部类的实现。和你一样吗?首先,我只关注内部类代码的意图。它只是一个空的实现或默认异常报告器的占位符。因此,如果我在实践中使用这个片段,空的内部类本身就不能使这个引用转义,对吗?