Java是按值传递而不是通过引用传递
Java编程语言中最大的困惑之一是java是Pass by Value还是Pass by Reference。我在采访中经常提出这个问题,但仍然看到受访者对此感到困惑。所以我想写一篇关于它的帖子来澄清它周围的所有混乱。
首先,我们应该理解通过值传递或通过引用传递的含义。
传递值:将方法参数值复制到另一个变量,然后传递复制的对象,这就是它被称为按值传递的原因。
通过引用传递:将实际参数的别名或引用传递给方法,这就是它被称为按引用传递的原因。
Java总是按值传递而不是通过引用传递,我们可以用一个简单的例子来证明它。
假设我们有一个Balloon
类似下面的课程。
package com.journaldev.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.journaldev.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=Redblue color=Blueblue color=Red
如果你看一下输出的前两行,很明显swap方法没有用。这是因为Java是按值传递的,这个swap()方法测试可以与任何编程语言一起使用,以检查它是通过值传递还是通过引用传递。
让我们一步一步地分析程序的执行情况。
Balloon red = new Balloon("Red");Balloon blue = new Balloon("Blue");
当我们使用new运算符创建类的实例时,将创建实例,并且变量包含保存对象的内存的引用位置。对于我们的示例,我们假设“red”指向50并且“blue”指向100,这些是两个Balloon对象的内存位置。
现在,当我们调用swap()方法时,会创建两个新变量o1和o2,分别指向50和100。
所以下面的代码片段解释了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}
第一行是重要的一行,当我们调用一个方法时,在参考位置的Object上调用该方法。此时,气球指向100,因此它的颜色变为红色。
在下一行中,气球参考被更改为200,并且执行的任何其他方法都发生在存储器位置200处的对象上,并且对存储器位置100处的对象没有任何影响。这解释了我们的程序输出的第三行打印蓝色=红。
我希望上面的解释清楚所有的疑问,只记得变量是引用或指针,它的副本传递给方法,所以java总是按值传递。您将更清楚地了解堆内存和堆栈内存以及存储不同对象和引用的位置,有关参考程序的详细说明,请阅读Java堆与堆栈。
更新:我收到了很多评论,似乎仍然存在很多混乱,所以我制作了一个视频教程来详细解释这一点。