Java是否真的按值传递对象?

可能重复: Java是否通过引用传递?

public class myClass{ public static void main(String[] args){ myObject obj = new myObject("myName"); changeName(obj); System.out.print(obj.getName()); // This prints "anotherName" } public static void changeName(myObject obj){ obj.setName("anotherName"); } } 

我知道Java通过值传递,但为什么它在前面的例子中通过引用传递obj并更改它?

Java总是按值传递参数,而不是通过引用传递参数。 在您的示例中,您仍然通过其值传递obj ,而不是引用本身。 在方法changeName ,您将另一个(本地)引用obj分配给您作为参数传递的同一对象。 修改该引用后,您将修改原始引用obj ,该引用将作为参数传递。


编辑:

让我通过一个例子解释一下:

 public class Main { public static void main(String[] args) { Foo f = new Foo("f"); changeReference(f); // It won't change the reference! modifyReference(f); // It will change the object that the reference refers to! } public static void changeReference(Foo a) { Foo b = new Foo("b"); a = b; } public static void modifyReference(Foo c) { c.setAttribute("c"); } } 

我将逐步解释这个:

1-声明名为fFoo类型的引用,并将其分配给类型为Foo的新对象,其属性为"f"

 Foo f = new Foo("f"); 

在此输入图像描述

2-从方法方面,声明了名为a的类型为Foo的引用,并且它最初被赋值为null

 public static void changeReference(Foo a) 

在此输入图像描述

3-当您调用方法changeReference ,引用a将被分配给作为参数传递的对象。

 changeReference(f); 

在此输入图像描述

4-声明名为b的类型为Foo的引用,并将其赋值给属性为"b" Foo类型的新对象。

 Foo b = new Foo("b"); 

在此输入图像描述

5- a = b将引用a NOT f重新分配给其属性为"b"的对象。

在此输入图像描述


6-当您调用modifyReference(Foo c)方法时,将创建引用c并将其分配给具有属性"f"的对象。

在此输入图像描述

7- c.setAttribute("c"); 将更改引用c指向它的对象的属性,并且它是引用f指向它的同一对象。

在此输入图像描述

我希望你现在明白如何将对象作为参数传递在Java中:)

在Java中,对象句柄或对象的标识被视为值。 按值传递意味着传递此句柄,而不是对象的完整副本。

术语“通过引用传递”中的“引用”也不意味着“引用对象”。 它表示“引用变量” – 可以存储值的函数定义(或者更确切地说是调用帧)中的命名“存储桶”。

通过引用传递意味着被调用的方法可以在调用方法中更改变量值 。 (例如,在C标准库中,函数scanf这种方式工作。)这在Java中是不可能的。 您始终可以更改对象的属性 – 它们不被视为其“值”的一部分。 它们是完全不同的独立物体。

你正在改变obj属性 ,而不是改变obj (参数)本身。

关键在于,如果你将obj指向changeName中的其他changeName ,则更改将不会反映在main

有关进一步说明,请参阅此post 。

它没有改变obj(你的代码也没有改变它)。 如果通过引用传递,你可以写:

 public static void changeName(myObject obj){ obj = new myObject("anotherName"); } 

并使用main方法打印“anotherName”。

Java正在传递您传递给函数的副本。 当它是基本类型时 – 它将是值的副本。 当它是一个对象时 – 你传递了参考副本。 在您的代码示例中,您正在修改其中一个对象属性,但不修改引用本身,因此名称将被更改。 但是,如果您想在changeName函数中将新对象分配给obj变量,那么您将更改引用,因此外部obj将具有旧值。

它将对obj的引用作为一个值传递(我知道有点令人困惑:))。

所以我们假设它复制了指向obj值的指针并传递了它。

这意味着你可以做以下事情:

  public static void changeName(myObject obj){ obj.setName("anotherName"); obj = new myObject(); } 

和声明

 System.out.print(obj.getName()); 

仍然会引用旧对象(你做的setName)。