Java是按值传递而不是按引用传递
Java编程语言中最大的困惑之一是java是按值传递还是按引用传递。
我在访谈中经常问这个问题,但仍然看到受访者对此感到困惑。
所以我想写一篇关于它的文章,以消除周围所有的困惑。
首先,我们应该了解按值传递或者按引用传递的含义。
按值传递:将方法参数值复制到另一个变量,然后传递复制的对象,这就是为什么将其称为按值传递的原因。
按引用传递:将实际参数的别名或者引用传递给方法,这就是为什么将其称为按引用传递的原因。
Java始终是按值传递而不是按引用传递,我们可以通过一个简单的示例来证明它。
假设我们有一个如下所示的"气球"类。
package com.theitroad.test; 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; } }
我们有一个简单的程序,带有一个通用方法来交换两个对象,该类如下所示。
package com.theitroad.test; public class Test { public static void main(String[] args) { Balloon red = new Balloon("Red"); //memory reference 50 Balloon blue = new Balloon("Blue"); //memory reference 100 swap(red, blue); System.out.println("red color="+red.getColor()); System.out.println("blue color="+blue.getColor()); foo(blue); System.out.println("blue color="+blue.getColor()); } private static void foo(Balloon balloon) { //baloon=100 balloon.setColor("Red"); //baloon=100 balloon = new Balloon("Green"); //baloon=200 balloon.setColor("Blue"); //baloon = 200 } //Generic swap method public static void swap(Object o1, Object o2){ Object temp = o1; o1=o2; o2=temp; } }
当我们执行上面的程序时,我们得到以下输出。
red color=Red blue color=Blue blue color=Red
如果看一下输出的前两行,很明显交换方法无效。
这是因为Java是按值传递的,此swap()方法测试可与任何编程语言一起使用,以检查它是按值传递还是按引用传递。
让我们逐步分析程序执行情况。
Balloon red = new Balloon("Red"); Balloon blue = new Balloon("Blue");
当我们使用new运算符创建类的实例时,将创建该实例,并且变量包含保存对象的内存的引用位置。
在我们的示例中,假设"红色"指向50,"蓝色"指向100,这是两个Balloon对象的存储位置。
现在,当我们调用swap()方法时,将创建两个分别指向50和100的新变量o1和o2。
因此,下面的代码片段说明了swap()方法执行中发生的情况。
public static void swap(Object o1, Object o2){ //o1=50, o2=100 Object temp = o1; //temp=50, o1=50, o2=100 o1=o2; //temp=50, o1=100, o2=100 o2=temp; //temp=50, o1=100, o2=50 } //method terminated
请注意,我们正在更改o1和o2的值,但是它们是"红色"和"蓝色"参考位置的副本,因此实际上"红色"和"蓝色"的值以及输出均没有变化。
如果您已经了解了这一点,则可以轻松理解造成混乱的原因。
由于变量只是对对象的引用,因此我们很困惑要传递引用,因此java通过引用传递。
但是,我们正在传递参考的副本,因此它是按值传递的。
我希望它现在消除所有疑问。
现在,让我们分析foo()方法的执行情况。
private static void foo(Balloon balloon) { //baloon=100 balloon.setColor("Red"); //baloon=100 balloon = new Balloon("Green"); //baloon=200 balloon.setColor("Blue"); //baloon = 200 }
第一行很重要,当我们调用方法时,该方法在对象的引用位置处被调用。
此时,气球指向100,因此其颜色更改为红色。
在下一行中,ballon引用更改为200,并且在存储位置200上的对象上发生了任何其他已执行的方法,并且对存储位置100上的对象没有任何影响。