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

Java真的是按值传递对象吗?,java,parameter-passing,terminology,pass-by-reference,pass-by-value,Java,Parameter Passing,Terminology,Pass By Reference,Pass By Value,可能重复: 我知道Java是通过值传递的,但为什么在前面的示例中它通过引用传递obj并对其进行更改?Java总是通过值传递参数,而不是通过引用。在您的示例中,您仍然通过其值传递obj,而不是引用本身。在方法changeName中,将另一个(本地)引用obj指定给作为参数传递的同一对象。修改该引用后,即修改原始引用,obj,该引用作为参数传递 changeReference(f); 编辑: 让我通过一个例子来解释这一点: public class Main { public sta

可能重复:


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

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

changeReference(f);

编辑:

让我通过一个例子来解释这一点:

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-声明名为
f
Foo
类型的引用,并将其分配给具有属性
Foo
类型的新对象

2-从方法方面,声明了一个名为
a
Foo
类型的引用,并将其初始分配给
null

public static void changeReference(Foo a)

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

changeReference(f);

4-声明名为
b
Foo
类型的引用,并将其分配给具有属性
“b”
Foo
类型的新对象

5-
a=b
正在将引用
a
而不是
f
重新分配给其属性为
“b”
的对象


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

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

我希望您现在了解在Java中如何将对象作为参数传递:)

您正在更改
obj
的属性,而不是更改
obj
(参数)本身

关键是,如果您将
obj
指向
changeName
中的其他内容,则该更改不会反映在
main


请参阅以获得进一步澄清。

它将引用作为值传递给obj(我知道有点混淆:)

假设它复制了指向obj值的指针,并传递它

这意味着您可以执行以下操作:

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

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

仍然要引用旧对象(您使用的setName)。

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

术语“通过引用”中的“引用”也不是指“引用对象”。它的意思是“对变量的引用”——在函数定义(或者更确切地说,调用框架)中可以存储值的命名“bucket”

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

它没有改变obj(您的代码无论如何也不会改变它)。 如果它是通过引用传递的,您可以写:

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

并通过main方法打印“anotherName”。

Java正在将您要传递的内容的副本传递给您的函数。当它是基元类型时-它将是值的副本。当它是一个对象时-您正在传递引用副本。在您的代码示例中,您修改的是一个对象属性,而不是引用本身,因此名称将被更改。但是,当您想在changeName函数中将新对象分配给obj变量时,您正在更改引用,因此外部obj将有一个旧值。

这已经被询问过一百万次。非常感谢您的详细解释。现在我得到了什么“引用obj作为值”或“发送引用副本”意思是:)这些图表确实有助于让这些概念变得清晰!非常感谢。这个解释很清楚,但我还是有点困惑。在步骤3中,“a”指向属性为f的对象。对我来说,“a”似乎指向“f”也指向的对象的引用。如果对象通过值传递,“a”和“f”都应该有自己的对象。但是,它们实际上共享相同的对象(即,它们指向同一对象的引用)。只需一句小小的注释:myObject应该是myObject。我很欣赏这个答案,因为它解释了在Java中,对象属性不被视为其“值”的一部分。但在我的世界里,允许一个具有自己作用域的函数或方法修改其作用域之外的变量(或对象),而调用方法的作用域中的变量(或对象)是“按引用传递”,对不起,Java伙计们。那么,你的观点是什么?不同的语言有不同的概念模型和术语。只要“您的世界”不是Java世界,或者不是Java的一个亲戚的世界,它在这里就不是真正相关的,不是吗?我还可以说PHP和Perl是通过本机实现“pass-by-deep-copy”而被淘汰的,但这只是语义,对任何人都没有用处。Java的术语大致与C的工作方式一致——通过代码> FoO或和Foo< /C>之间的区别。在C++中,java java的另一个祖先,通过引用而不是值再次与函数是否直接在堆栈帧中改变状态无关。这就是常量的作用。(尽管C++具有非凡的灵活性,但通过传递值来复制对象肯定是可能的
System.out.print(obj.getName());
public static void changeName(myObject obj){
    obj = new myObject("anotherName");
}