如何解释Java中的浅拷贝与按值传递?

时间:2011-10-31 14:03:49

标签: java

根据我对Java的理解,一切都是通过价值传递的。然而,当你开始谈论包含其他对象的对象时,事情会变得有趣,我希望能够更好地沟通,并确保我也完全理解。所以我的观点是,实际上只复制了对象中的原语,另一方面它包含的任何对象......这些对象的值不会被复制,而只是这些引用的副本。

所以,如果我们与这些成员有一些对象

public class SomeObject {
   private String name;
   private String address;
   private  List<String> friends;

   public SomeObject(String name, String address, List<String> friends) {
      this.name = name;
      this.address = address;
      this.friends = friends;
   }
}

我们这样做了:

List<String> friendsList = new ArrayList<String>();
        friendsList.add("bob");
        friendsList.add("joe");

        SomeObject so1 = new SomeObject("mike", "123 street", friendsList);

        friendsList.add("zoe");
        friendsList.add("rick");
        SomeObject so2 = new SomeObject("david", "300 ave", friendsList);

        System.out.println(so1.getName() + " " + so1.getAddress());
        for (String friend : so1.getFriends()) {
            System.out.println(friend);
        }

        System.out.println(so2.getName() + " " + so2.getAddress());
        for (String friend : so2.getFriends()) {
            System.out.println(friend);
        }

我们的输出是:

mike 123 street
bob
joe
zoe
rick
david 300 ave
bob
joe
zoe
rick

即使我们创建了2个单独的对象,它们也都保留了对原始好友列表的引用。这就是为什么当人们说Java总是按值传递时,我会有点绊倒。

10 个答案:

答案 0 :(得分:10)

引用按值传递,因此复制指向列表的指针,而不是列表本身。

答案 1 :(得分:6)

对列表的引用是按值传递的,而不是列表本身,这意味着,您无法在friendsList的构造函数中更改SomeObject,但您可以更改它指向的内容。 / p>

例如,如果构造函数是这样的:

public SomeObject(String name, String address, List<String> friends) {
    this.name = name;
    this.address = address;
    this.friends = friends;
    friends = new ArrayList<String>();
}

虽然您已将新列表分配给friends,但仍会获得相同的输出。

答案 2 :(得分:3)

Java总是按值传递参数。在您的情况下,对象引用按值传递。请参阅此文章,解释如何以及为何。

http://javadude.com/articles/passbyvalue.htm

答案 3 :(得分:1)

我听说Java的内存模型被描述为通过“引用值”传递。任何“原始”类型(int,例如)都是按值传递的。任何扩展Object的东西也都是通过值传递的...但是对象的值是对它在堆中的位置的引用

答案 4 :(得分:1)

Java是按值传递的。事情是,你所谓的对象实际上是对象的引用。其价值已通过..

答案 5 :(得分:1)

所有内容都按值传递,但对象本身从不传递。只是它的引用按值传递。

将对象视为存储在某种仓库中,对于每个对象,您都有一个标识符,指出对象所在的位置。好的,现在无论您将对象从方法传递到另一个方法,只需传递标识符即可。

答案 6 :(得分:1)

按值传递的是对列表的引用,而不是列表本身。如果您对C ++知之甚少,那么它就像复制列表的指针一样。这2个对象有2个不同的引用,引用了SAME列表。这是对此输出的解释。

答案 7 :(得分:1)

以下varInt包含值“2”

int varInt = 2; 

以下varObj值“恰好是新对象的引用”

Object varObj = new Object(); 

所以,如果你按如下方式调用方法 -

someVar.method1(varInt); // the value 2 is passed here

someVar.method2(varObj); // the value which is the reference is passed here

所以Java总是按值传递。

答案 8 :(得分:0)

Java不是通过值传递的。只有基元通过值传递,对象通过引用传递。由于您对两个朋友列表使用相同的列表,因此朋友也是一样的。

答案 9 :(得分:0)

只有Java中的基元通过值传递,对象和数组都是通过引用传递的。