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");
}