局部内部类访问它所在方法的局部变量时,要求该局部变量必须声明为final的原因

这是java的一条规则。那么为什么会有这条规则呢?要想弄懂这个问题,就需要弄懂局部内部类对象和局部变量的生命周期谁更长的问题。

首先,看一段代码,以没有将变量声明为final的代码作为例子,代码如下:

复制代码

 1 class Outer{
 2     
 3     Object obj;
 4     public void outerMethod() {
 5         
 6         //局部变量
 7         int x = 5;
 8         //定义在方法中的内部类称为局部内部类
 9         class Inner{
10 
11             public String toString() {
12                 System.out.println(x);//访问了局部变量x
            return null; 
13             }
14         }
15         //创建内部类实例
16         Inner in = new Inner();
17         in.toString();
18         //将内部类实例的引用赋值给obj
19         obj = in;
20     }
21 }
22 public class HelloDemo {
23     
24     public static void main(String[] argr) {
25         Outer out = new Outer();
26         out.outerMethod();
27       
28   }
29 }

复制代码

  如上面的第7行代码所示,变量x没有被声明为final,如果是这样的话,当执行完第26行的outMethod()方法后,outMethod()方法将出栈,出栈后outMethod()方法里面定义的所有变量(x 和 in)都死亡了,(但是此时内部类的对象还活着,直到它不再被使用才会被回收,也就是说此内部类对象的生命周期比局部变量的生命周期长),并且在变量 in 死亡之前,in 的值赋值给了成员变量obj(第19行代码),这时obj 指向了内部类的对象,如果此时在27行执行一条代码: out.obj.toString();那么这条代码将会访问到局部变量 x,但是此时 x 已经死亡了,内部类对象已经访问不到 x 了,因此这是相互矛盾的。所以上面的代码实际上并不能编译通过。(在jdk8.0能编译通过,那是因为它检测到局部内部类访问了 x,会默认给 x 的前面加上隐式的final,如果在第8行加上一句代码:x = 4;编译器将会报错,因为final不允许 x 的值改变)

  如果局部变量 x 被声明为final后(在第七行的int前加上final),x 就代表了一个常量,那么第15行的代码实际上就变成了 System.out.println(5);,这时内部类相当于访问了一个数字5。这是没任何问题的,因此局部内部类访问它所在方法的局部变量时,要求该局部变量必须声明为final。究其根本原因,是局部内部类对象的生命周期比局部变量的生命周期长。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值