介绍
许多Java程序员都在质疑Java是按值传递还是按引用传递。本文总结了为什么Java始终是按值传递的原因。
首先,按值传递和按引用传递是什么意思呢?
- 按值传递:方法参数值被复制到另一个变量,然后将复制的对象传递给方法。方法使用复制品。
- 按引用传递:将实际参数的别名或引用传递给方法。方法访问实际参数。
通常,对这些术语的困惑是由于Java中的“对象引用”概念引起的。从技术上讲,Java始终是按值传递的,因为即使变量可能持有对对象的引用,该对象引用也是表示对象在内存中位置的值。因此,对象引用是按值传递的。
引用数据类型和基本数据类型都是按值传递的。了解有关Java中数据类型的更多信息。
除了理解数据类型,了解Java中的内存分配也很重要,因为引用数据类型和基本数据类型的存储方式不同。
演示按值传递
以下示例演示了在Java中如何传递值。
示例程序使用以下类:
public class Balloon {
private String color;
public Balloon() {}
public Balloon(String c) {
this.color = c;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
以下示例程序使用了一个通用方法,swap()
,它交换了两个变量。另一个方法,changeValue()
,尝试更改变量的值。
public class Test {
public static void main(String[] args) {
Balloon red = new Balloon("Red"); // 内存引用 = 50
Balloon blue = new Balloon("Blue"); // 内存引用 = 100
swap(red, blue);
System.out.println("After the swap method executes:");
System.out.println("`red` color value = " + red.getColor());
System.out.println("`blue` color value = " + blue.getColor());
changeValue(blue);
System.out.println("After the changeValue method executes:");
System.out.println("`blue` color value = " + blue.getColor());
}
// 通用交换方法
public static void swap(Object o1, Object o2){
Object temp = o1;
o1 = o2;
o2 = temp;
}
private static void changeValue(Balloon balloon) { // balloon = 100
balloon.setColor("Red"); // balloon = 100
balloon = new Balloon("Green"); // balloon = 200
balloon.setColor("Blue"); // balloon = 200
}
}
执行示例程序时,您将获得以下输出:
OutputAfter the swap method executes:
'red' color value = Red
'blue' color value = Blue
After the changeValue method executes:
'blue' color value = Red
输出显示swap()
方法未交换原始对象的颜色值。这有助于证明Java是按值传递的,因为swap()
方法只作用于原始对象引用值的副本。
这个swap()
方法的测试可以用于任何编程语言,以检查它是按值传递还是按引用传递。
解释了示例swap()
方法
当您使用new
运算符创建类的实例时,对象将被创建,并且变量包含对象保存在内存中的位置。
Balloon red = new Balloon("Red");
Balloon blue = new Balloon("Blue");
下面是swap()
方法执行时发生的步骤逐步解析:
-
假设
red
指向内存位置50,blue
指向内存位置100,并且这些是两个Balloon
对象的内存位置。 -
当类使用
red
和blue
变量作为参数调用swap()
方法时,将创建两个新的对象变量o1
和o2
。o1
和o2
同样指向内存位置50和100。 -
以下的代码片段解释了
swap()
方法中的操作:public static void swap(Object o1, Object o2) { // o1 = 50, o2 = 100 Object temp = o1; // 将o1的对象引用值赋给temp:temp = 50, o1 = 50, o2 = 100 o1 = o2; // 将o2的对象引用值赋给o1:temp = 50, o1 = 100, o2 = 100 o2 = temp; // 将temp的对象引用值赋给o2:temp = 50, o1 = 100, o2 = 50 } // 方法结束
-
o1 和 o2 的值已交换,但由于这些值是对 red 和 blue 内存位置的副本,因此 red 和 blue 的颜色值不会发生变化。
由于变量包含对对象的引用,常见的错误是认为您正在传递引用并且 Java 是按引用传递的。但是,您传递的是引用的副本,因此它是按值传递的。
示例 changeValue() 方法解释
示例程序中的下一个方法更改了由blue
变量引用的对象的颜色值:
private static void changeValue(Balloon balloon) { // balloon = 100
balloon.setColor("Red"); // balloon = 100
balloon = new Balloon("Green"); // balloon = 200
balloon.setColor("Blue"); // balloon = 200
}
以下是changeValue()
方法中发生的步骤逐步分解:
-
该类在
blue
变量上调用changeValue()
方法,该变量引用内存位置100。第一行创建了一个引用,也指向内存位置100。内存位置100处对象的颜色值更改为"Red"
。 -
第二行创建了一个新对象(颜色值为
"Green"
)。新对象位于内存位置200。在balloon
变量上执行的任何进一步方法都会作用于内存位置200处的对象,并且不会影响内存位置100处的对象。新的balloon
变量覆盖了第1行中创建的引用,并且第1行中的balloon
引用在此方法中不再可访问。 -
第三行更改了内存位置200处新
Balloon
对象的颜色值为"蓝色"
,但不影响由blue
在内存位置100引用的原始对象。这解释了为什么示例程序输出的最后一行打印blue color value = Red
,这反映了从第1行的变化。
结论
在本文中,您了解了Java为什么是传值调用。继续学习更多的Java教程。
Source:
https://www.digitalocean.com/community/tutorials/java-is-pass-by-value-and-not-pass-by-reference