Java真的按值传递对象吗?

时间:2011-10-25 17:44:29

标签: java parameter-passing terminology pass-by-reference pass-by-value

  

可能重复:   Is Java pass by reference?

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并更改它?

6 个答案:

答案 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"

Enter image description here

2-从方法方面,声明了名为Foo f = new Foo("f"); 的{​​{1}}类型的引用,并且它最初分配给Foo

a

Enter image description here

3-当你调用方法null时,引用public static void changeReference(Foo a) 将被分配给作为参数传递的对象。

changeReference

Enter image description here

4-声明名为a的{​​{1}}类型的引用,并将其分配给类型为changeReference(f); 的新对象,其属性为b

Foo

Enter image description here

5- Foo正在将引用"b" NOT Foo b = new Foo("b"); 重新分配给其属性为a = b的对象。

Enter image description here


6-当您调用a方法时,会创建一个引用f,并将其分配给具有属性"b"的对象。

Enter image description here

7- modifyReference(Foo c)会更改引用c的对象的属性指向它,并且它是引用"f"指向它的同一对象。

Enter image description here

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

答案 1 :(得分:9)

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

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

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

答案 2 :(得分:2)

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

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

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

答案 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的对象)。