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
并更改它?
答案 0 :(得分:98)
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-声明名为f
的{{1}}类型的引用,并将其分配给类型为Foo
的新对象,其属性为Foo
。
"f"
2-从方法方面,声明了名为Foo f = new Foo("f");
的{{1}}类型的引用,并且它最初分配给Foo
。
a
3-当你调用方法null
时,引用public static void changeReference(Foo a)
将被分配给作为参数传递的对象。
changeReference
4-声明名为a
的{{1}}类型的引用,并将其分配给类型为changeReference(f);
的新对象,其属性为b
。
Foo
5- Foo
正在将引用"b"
NOT Foo b = new Foo("b");
重新分配给其属性为a = b
的对象。
6-当您调用a
方法时,会创建一个引用f
,并将其分配给具有属性"b"
的对象。
7- modifyReference(Foo c)
会更改引用c
的对象的属性指向它,并且它是引用"f"
指向它的同一对象。
我希望您现在了解如何将对象作为参数传递在Java中:)
答案 1 :(得分:9)
在Java中,对象句柄或对象的标识被视为值。按值传递意味着传递此句柄,而不是对象的完整副本。
术语“通过引用传递”中的“引用”也不表示“引用对象”。它表示“引用变量” - 可以存储值的函数定义(或者更确切地说是调用框架)中的命名“存储桶”。
通过引用传递意味着被调用的方法可以在调用方法中更改变量值。 (例如,在C标准库中,函数scanf
以这种方式工作。)这在Java中是不可能的。您始终可以更改对象的属性 - 它们不被视为其“值”的一部分。它们是完全不同的独立物体。
答案 2 :(得分:2)
答案 3 :(得分:2)
它没有改变obj(你的代码无论如何都不会改变它)。 如果通过引用传递,你可以写:
public static void changeName(myObject obj){
obj = new myObject("anotherName");
}
并使用main方法打印“anotherName”。
答案 4 :(得分:1)
Java正在传递您传递给函数的副本。当它是基本类型时 - 它将是值的副本。当它是一个对象时 - 你传递了参考副本。在您的代码示例中,您正在修改其中一个对象属性,但不修改引用本身,因此名称将被更改。但是,如果您想在changeName函数中将新对象分配给obj变量,那么您将更改引用,因此外部obj将具有旧值。
答案 5 :(得分:0)
它将对obj的引用作为一个值传递(我知道有点混乱:))。
所以让我们说它会复制指向obj值的指针并传递它。
这意味着您可以执行以下操作:
public static void changeName(myObject obj){
obj.setName("anotherName");
obj = new myObject();
}
和陈述
System.out.print(obj.getName());
仍然会引用旧对象(你做setName的对象)。