Java 基础的重要知识点

本文最后更新于:2023年7月9日 晚上

Java 基础的重要知识

Java 的变量是值传递还是引用传递?

我记得在最开始学习 Java 的时候,关于变量传参的方式是这样定义的:

对于基本数据类型 (int, double, long, float) Java 是值传递,而对于引用数据类型 (Array, String, List) Java 是引用传递,也就是直接传递变量地址。

值传递的例子

不过,最近看了一篇文章发现事实并非如此。先说结论:在 Java 中,所有变量都是值传递,无论是基本类型还是引用类型都是如此。 那么现在问题来了,既然 Java 中引用类型也是值传递,为什么方法内的操作变量会影响到外部的变量呢?看下方这段代码:

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
System.out.println("before change arr[0] = "+ arr[0]);
change(arr);
System.out.println("after change arr[0] = "+ arr[0]);
}

public static void change(int[] array) {
// 将数组的第一个元素变为0
array[0] = 0;
}

输出结果:

1
2
before change arr[0] = 1
after change arr[0] = 0

可以看到,我们在 change 方法中对 array 进行修改后,函数外也看到了效果。为什么值传递呈现了引用传递的效果呢?关键点在于,Java 中传递的是变量地址值的副本。引用类型的参数在传递时,会将引用的地址值,复制一份传递到方法内部。前面 change 函数接收的实际上是 arr 地址的副本。在 change 方法内部,arrarray 两个变量都指向了同一个地址。所以,方法 change 对数组的修改会同步到方法外部。

引用传递的例子

我们再看一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Person {
private String name;
// 省略构造函数、Getter&Setter方法
}

public static void main(String[] args) {
Person xiaoZhang = new Person("小张1");
Person xiaoLi = new Person("小李2");
swap(xiaoZhang, xiaoLi);
System.out.println("xiaoZhang:" + xiaoZhang.getName());
System.out.println("xiaoLi:" + xiaoLi.getName());
}

public static void swap(Person person1, Person person2) {
// swap 前 xz = p1,xl = p2
Person temp = person1;
person1 = person2;
person2 = temp;

// swap 后,xz = xl = p2 ,xl = xz = p1
System.out.println("person1:" + person1.getName());
System.out.println("person2:" + person2.getName());

person1.setName("person1 xl ");
}

最终输出结果:

1
2
3
4
person1:xiaoLi = 小李2
person2:xiaoZhang = 小张1
xiaoZhang:xiaoZhang = 小张1
xiaoLi:person1 xl

这个例子中,xiaoZhang = 小张1,xiaoLi = 小李2,我们在 swap 函数中交换了它们两个然后并打印。从输出结果中可以看出,在函数体内,它们两个确实是已经交换。但在函数体外部再打印,它们的值却没有任何变化。这也就印证了, Java 中引用变量传递的是地址的副本,而不是地址本身这个理论了。
swap 前
我们在方法中交换两个变量,也只是交换的两个副本变量指向的地址,函数外部变量指向的地址的没有任何影响。
swap 后

这种方式的好处在于,方法内部的操作不会莫名其妙地对外部造成影响,减少意想不到的结果。

总结

  • Java 中,变量的传递都是值传递,不存在引用传递。
  • 对于引用变量,在传递时,是先复制的引用变量的地址,然后再传递。

Java 基础的重要知识点
https://travelerentity.github.io/2023/Java-基础的重要知识点/
作者
LinYun
发布于
2023年7月8日
许可协议