深刻理解从内部类引用的本地变量必须是最终变量或实际上的最终变量这
2026-01-04 本文已影响0人
程序圆_
1、什么是最终变量,什么是实际变量。
最终变量也就是,有关键字:final修饰的,后面不可改变。
例如:
图1、最终变量
实际变量也就是没有final修饰的变量,但是其在声明时就被赋值后,它的值就没有进行更改。
例如:
图2、实际变量(这里是错误用法)
没有后面的x=20就是effective final。
2、为什么JAVA会出现这个限制。
核心就是其生命周期不一样:局部变量存在方法调用期间,方法结束就被销毁了。而内部类对象可能在方法结束后依然存在,如果内部类直接“引用”局部变量,而该内存已经被释放就会出错。
所以JAVA的解决方案是,Java 在编译时会将局部变量的值拷贝一份给内部类。为了保证语义一致(内部类看到的值不会“意外变化”),这个变量不能被修改。所以会出现问题。
3、修改方案
1、如果是在类中的话可在设计的变量上将局部变量变成实例变量前面加private。
(原因解释:因为外部对象本身必须存在(否则内部类无法存活)那么实例变量也会存在,所以它的成员变量天然就是“可达且一致”的,无需final限制。)
例如:
图3、修改方案1
2、可以在局部变量声明前加final(但是如果后面值需要被修改,就会出现错误)
例如:final int count =0;
3、也可以将局部变量改成数组形式。(不推荐)
(原因解释:后面的内部类引用的是数组的地址,地址并没有进行修改,只是改变了其中的值,所以可以。)
当然聪明的同学想到那不怕出现和局部变量那样的悬挂指针或者已释放内存错误吗?这里解释一下,其数组的引用是放在栈内,而数组本身是放在堆中的,即使方法结束、局部变量销毁,只要内部类还持有对该数组对象的引用,该对象就不会被垃圾回收。
图5、修改方案3
这就是本人对于这个问题的全部理解,希望可以解答大家的疑惑,也望大家在评论中给予补足。