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