天天看点

为什么匿名内部类只能访问final修饰的变量?

Local classes can most definitely reference instance variables. The reason they cannot reference non final local variables is because the local class instance can remain in memory after the method returns. When the method returns the local variables go out of scope, so a copy of them is needed. If the variables weren’t final then the copy of the variable in the method could change, while the copy in the local class didn’t, so they’d be out of synch.
Anonymous inner classes require final variables because of the way they are implemented in Java. An anonymous inner class (AIC) uses local variables by creating a private instance field which holds a copy of the value of the local variable. The inner class isn’t actually using the local variable, but a copy. It should be fairly obvious at this point that a “Bad Thing”™ can happen if either the original value or the copied value changes; there will be some unexpected data synchronization problems. In order to prevent this kind of problem, Java requires you to mark local variables that will be used by the AIC as final (i.e., unchangeable). This guarantees that the inner class’ copies of local variables will always match the actual values.

 ​

首先内部类肯定是可以引用实例变量的,他们无法引用非final关键字修饰的变量的原因是内部类在方法返回后还会存在内存中。当方法返回,方法的局部变量超出了有效范围(方法内的变量失效),这时候就需要拷贝一份变量给内部类使用。如果,变量不是final修饰,那么拷贝的值可能会发生改变,但是拷贝到内部类的变量却无法同步更新。

匿名内部类要求使用final修饰的变量是因为Java的实现方式,一个匿名内部类(AIC)可以使用方法变量是通过拷贝一份变量作为内部类的私有变量。内部类并不是真正的使用方法的局部变量,而是一份拷贝。在这点上,如果原来的值和拷贝的值发生变化,很显然会导致不好的事情发生,可能会导致不可预期的数据同步问题发生。为了避免这类型的问题发生,Java要求你将方法变量用final修饰,这保证了内部类拷贝的方法变量总是与实际的变量一致。

tips:java7需要显示声明final变量,java8会自动为你添加final关键字修饰