为什么匿名类可以访问封闭类的非最终类成员

2022-09-03 07:30:00

我们知道,在匿名类中只能访问最终的局部变量,这里有一个很好的理由:为什么在匿名类中只能访问最终变量?

但是,我发现如果匿名类是封闭类的成员字段,则匿名类仍然可以访问该变量:如何从匿名类内部访问封闭类实例变量?

我很困惑。我们确保在匿名类中只能访问最终的局部变量,因为我们不希望该变量在匿名类和局部函数之间不同步。同样的原因应该适用于我们尝试访问匿名类中的非最终封闭类成员的情况。

为什么这不是一个问题?


答案 1

对于局部变量,变量的副本是匿名类实例接收的副本。因此,必须先创建局部变量,然后才能在匿名类中使用,以便其值以后不会更改。final

对于封闭类的成员字段,则没有副本。相反,匿名类获取对封闭类的引用,从而访问外部类的任何/所有成员字段和方法。因此,即使字段的值发生更改,更改也会反映在匿名类中,因为它是相同的引用。

我很困惑。我们确保在匿名类中只能访问最终的局部变量,因为我们不希望该变量在匿名类和局部函数之间不同步。同样的原因应该适用于我们尝试访问匿名类中的非最终封闭类成员的情况。

如您所见,情况并非如此。复制只对局部变量进行,而不对封闭类的成员字段进行。当然,原因是匿名类包含对封闭类的隐式引用,并且通过该引用,它可以访问外部类的任何/所有成员字段和方法。

引用下面的链接:

成员变量在封闭对象的生存期内存在,因此内部类实例可以引用它。但是,局部变量仅在方法调用期间存在,并且编译器以不同的方式处理局部变量,因为该局部变量的隐式副本是作为内部类的成员生成的。如果不将局部变量声明为 final,则可以更改它,从而导致由于内部类仍然引用该变量的原始值而导致的细微错误。

引用:

1. 为什么非最终的“局部”变量不能在内部类中使用,而封闭类的非最终字段可以?


答案 2

非静态/内部类具有对封闭实例的引用。因此,它们可以隐式引用实例变量和方法。

如果它是一个参数,甚至封闭类也不知道它的任何信息,因为它只能从定义此变量的方法访问。

正如Y.S.已经指出的那样:

对于局部变量,变量的副本是匿名类实例获取的副本