什么叫 值传递&引用传递
值传递:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
引用传递:引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
举例
/**
* 证明java值传递demo
*
* @author miao
*/publicclassPassValueDemo {
publicstaticvoidmain(String[] args) {
inta=1;
Stringstr="1";
Useruser=newUser("阿花", 6);
System.out.println("调用方法前a为:" + a);
System.out.println("调用方法前str为:" + str);
System.out.println("调用方法前user为:" + user);
System.out.println("------------------------------------------");
convert(a, str, user);
System.out.println("------------------------------------------");
System.out.println("调用方法后a为:" + a);
System.out.println("调用方法后str为:" + str);
System.out.println("调用方法后user为:" + user);
}
privatestaticvoidconvert(int a, String str, User user) {
a = 2;
str = "2";
user.setAge(9);
user.setUsername("大壮");
System.out.println("调用方法中a为:" + a);
System.out.println("调用方法中str为:" + str);
System.out.println("调用方法中user为:" + user);
}
}
/**
* @author miao
*/classUser {
public String username;
publicint age;
publicUser(String username, int age) {
this.username = username;
this.age = age;
}
public String getUsername() {
return username;
}
publicvoidsetUsername(String username) {
this.username = username;
}
publicintgetAge() {
return age;
}
publicvoidsetAge(int age) {
this.age = age;
}
@Overridepublic String toString() {
return"User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
}
复制代码
程序的执行结果:
调用方法前a为:1
调用方法前str为:1
调用方法前user为:User{username='阿花', age=6}
------------------------------------------
调用方法中a为:2
调用方法中str为:2
调用方法中user为:User{username='大壮', age=9}
------------------------------------------
调用方法后a为:1
调用方法后str为:1
调用方法后user为:User{username='大壮', age=9}
我们可以看到,身为基本类型的int和被final修饰的String并没有改变,但是引用类型User改变了,所以,网上就有人得出了结论:java针对基本类型是值传递,对于引用类型是引用传递。但是!!!!这是错误的结论,不相信的话:
在convert()方法中str = "2";下面增加一行user = new User("小美", 18),让我们看看这样的结果是什么?
![](https://i-blog.csdnimg.cn/blog_migrate/bd71f55033c3774c2add491da5e62fb1.png)
程序的执行结果:
调用方法前a为:1
调用方法前str为:1
调用方法前user为:User{username='阿花', age=6}
------------------------------------------
调用方法中a为:2
调用方法中str为:2
调用方法中user为:User{username='大壮', age=9}
------------------------------------------
调用方法后a为:1
调用方法后str为:1
调用方法后user为:User{username='阿花', age=6}
从上述结果可以看出,当我们在 convert 方法中添加 user = new User("小美", 18)之后,“引用传递”就突然变值传递了?为什么?
这是因为,在 Java 语言中本质上只有值传递,也就说 Java 的传参只会传递它的副本,并不会传递参数本身。
即传入convert()时的user为 User user 的副本,指向同一个new User("阿花", 6)的堆地址,
当执行user = new User("小美", 18)时,指向的堆内存改变了,所以再进行任何操作都跟之前的堆地址没关系了,即证实了,传递的是一个副本。
虽然是个副本,但这个副本引用也是会指向堆内存地址的,副本引用和源数据引用指向同一个内存地址;
未执行user = new User("小美", 18)之前
![](https://i-blog.csdnimg.cn/blog_migrate/ff9f403088200bca62bfd2972a59bbee.png)
在方法函数中执行user = new User("小美", 18)之后
![](https://i-blog.csdnimg.cn/blog_migrate/0dee4fdb7d22410f68e9eda788b59ad9.png)
副本引用和源数据引用指向的是堆中不同的内存地址;