要明白这个问题,首先要知道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来限制修改,避免造成歧义。
标签:java,Demo,局部变量,public,User,new,setAge,final,user From: https://www.cnblogs.com/xc9497/p/16894185.html