java匿名内部类访问局部变量为啥要用final
要明白这个问题,首先要知道java参数传递方式只有值传递,即函数调用过程中形参的改变不会影响实参。允许一下代码:
1 public class Demo { 2 3 private User user; 4 public Demo(User user){ 5 user.setName("李四"); 6 user.setAge(234); 7 this.user=user; 8 } 9 10 public static void main(String[] args) { 11 User user=new User(); 12 user.setName("张三"); 13 user.setAge(20); 14 Demo demo=new Demo(user); 15 System.out.print(user); 16 } 17 18
哎?怎么和书上说的对不上?说好的值传递呢?这个问题也困扰了我一段时间。再修改一下运行:
1 public class Demo { 2 3 private User user; 4 public Demo(User user){ 5 user=new User(); 6 user.setName("李四"); 7 user.setAge(234); 8 this.user=user; 9 } 10 11 public static void main(String[] args) { 12 User user=new User(); 13 user.setName("张三"); 14 user.setAge(20); 15 Demo demo=new Demo(user); 16 System.out.print(user); 17 } 18 19 }
这一次我在第7行加了一行代码 user=new User(); 重新创建了对象,执行结果就完全不一样了。为啥会出现这种情况?这是因为java引用对象的传递是将实际参数的引用地址复制一份传给形参,即两个引用地址对应一个对象,当形参修改时实参也会跟着变化,即第一种情形。若形参重新创建一个对象,会重新分配一个新对象的引用地址,这样形参的修改不会影响实参,即第二情形。
ps:若参数是基本类型,那么传递的是复制基本类型的值,形参的改变不会影响实参。
了解的参数传递,我们来看下包含匿名内部类使用代码:
public class Demo { private User user; public Demo(User user){ user=new User(); user.setName("李四"); user.setAge(234); this.user=user; } public static void main(String[] args) { final User user=new User(); user.setName("张三"); user.setAge(20); //Demo demo=new Demo(user); //System.out.print(user); Thread thread=new Thread(new Runnable() { @Override public void run() { System.out.println(user); } }); thread.start(); } }
在看下匿名内部类Demo$1.class 反编译后结果
class Demo$1 implements Runnable { Demo$1(User var1) { this.val$user = var1; } public void run() { System.out.println(this.val$user); } }
编译器将匿名内部类所使用的局部变量传入了构造函数中,根据我们对前面参数传递的理解,这是一个复制的引用地址。但是从程序员的角度来看,这两个应该是一个对象。如果java不在语义上限制,有可能会造成我们人认为是一个对象,而机器理解是两个对象,造成程序得出结果和预期不符的情况,所以java在匿名类中引用局部变量必须用final来限制修改,避免造成歧义。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!