为什么Java只有值传递??
值传递: 调用函数时,将实参复制一份传给函数,函数中修改参数时不会影响实参
引用传递:调用函数时,将实参的地址传给函数,函数中修改参数会影响实参。
判断是值传递还是引用传递的标准,和传递参数的类型是没有关系的。
Java中的栈与堆
1-值传递
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | public class TestNum {public static void main(String[] args) {
 int num = 3;
 System.out.println("修改前的num值:"+num);
 changeValue(num);
 System.out.println("修改后的num值:"+num);
 }
 
 private static void changeValue(int num) {
 num = 5;
 System.out.println("形参num值:"+num);
 }
 }
 
 | 
结果:
| 12
 3
 
 | 修改前的num值:3形参num值:5
 修改后的num值:3
 
 | 
值传递不是简单的把实参传递给形参,而是,实参建立了一个副本,然后把副本传递给了形参。图中num是实参,然后创建了一个副本temp,把它传递给形参value,修改value值对实参num没有任何影响。

2-引用传递
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 
 | package java_learn;
 class User {
 private int age;
 private String name;
 public int getAge() {
 return age;
 }
 
 public void setAge(int age) {
 this.age = age;
 }
 
 public String getName() {
 return name;
 }
 
 public void setName(String name) {
 this.name = name;
 }
 
 public User(int age, String name) {
 this.age = age;
 this.name = name;
 }
 
 public User() {
 }
 
 @Override
 public String toString() {
 return "User{" +
 "age=" + age +
 ", name='" + name + '\'' +
 '}';
 }
 }
 public class TestUser {
 public static void main(String[] args) {
 User user = new User(18, "zhangsan");
 System.out.println("修改对象前:"+user);
 changeUser(user);
 System.out.println("修改对象后:"+user);
 }
 
 private static void changeUser(User user) {
 user.setAge(20);
 user.setName("lisi");
 }
 }
 
 | 
结果:
| 12
 
 | 修改对象前:User{age=18, name='zhangsan'}修改对象后:User{age=20, name='lisi'}
 
 | 
可以发现,传过去的user对象,属性值被改变了。由于,user对象存放在堆里边,其引用存放在栈里边,其参数传递图如下。
user是对象的引用,为实参,然后创建一个副本temp,把它传递给形参user1。但是,他们实际操作的都是堆内存中的同一个User对象。因此,对象内容的修改也会体现到实参user上。

3-传递类型是String类型
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | public class TestStr {public static void main(String[] args) {
 String str = new String("zhangsan");
 System.out.println("字符串修改前:"+str);
 changeStr(str);
 System.out.println("字符串修改后:"+str);
 }
 
 private static void changeStr(String str) {
 str = "lisi";
 }
 }
 
 | 
结果:
| 12
 
 | 字符串修改前:zhangsan字符串修改后:zhangsan
 
 | 
String也是引用类型,为什么在这又不变了呢?传递参数是引用类型,并不代表就是引用传递,其实它还是值传递。
图中,str是对象 zhangsan的引用,为实参,然后创建了一个副本temp,把它传递给了形参str1。此时,创建了一个新的对象 lisi ,形参str1指向这个对象,但是原来的实参str还是指向zhangsan。因此,形参内容的修改并不会影响到实参内容。
所以,两次打印结果都是zhangsan。

总结:
值传递,不论传递的参数类型是值类型还是引用类型,都会在调用栈上创建一个形参的副本。不同的是,对于值类型来说,复制的就是整个原始值的复制。而对于引用类型来说,由于在调用栈中只存储对象的引用,因此复制的只是这个引用,而不是原始对象。
最后,再次强调一下,传递参数是引用类型,或者说是对象时,并不代表它就是引用传递。引用传递不是用来形容参数的类型的,不要被“引用”这个词本身迷惑了。这就如同我们生活中说的地瓜不是瓜,而是红薯一样。
- 参数传递时,是拷贝实参的副本,然后传递给形参。(值传递)
- 在函数中,只有修改了实参所指向的对象内容,才会影响到实参。