如何正确复制对象

时间:2014-11-24 08:19:13

标签: java this

这可能已经被问到了,但由于我不太确定如何发表意见,我找不到它。

基本上

假设我们有类a,(参见下面的代码),我们想将它的一个实例a1复制到另一个实例a2。

所以,在我的主要内容中我会a1.copy(a2) 我知道使用copy2方法会有效。但是copy1不会。我只是想澄清为什么会这样。是因为参数只是对象的“副本”,所以对象本身(a2)不会改变。

class a {
    private int val;
    public class(int val){
        this.val = val; 
    }

    public void copy1(a obj){
        obj = this;
    }

    public void copy2(a obj) {
            obj.val = this.val;
    }
}

4 个答案:

答案 0 :(得分:1)

当您调用 copy1()方法时,该参数是对象 a obj 的引用的副本。当您将其设置为此( obj = this; )时,对象引用的副本将替换为当前对象,但原始对象和对您要调用的位置的对象的引用 copy1()方法保持不变。您只需更改对象引用的副本。

当您调用方法 copy2()时,那里没有完成参考工作,并且您正在逐个匹配变量(对象的属性)并且没有参考副本在那里工作。您正在更改对象本身。在这种情况下, this.val = obj.val; 也可以。

要获得更多理解,请检查this topic并检查其他语言(如C或C ++)如何处理参数传递问题。

答案 1 :(得分:1)

我想你可能想看看如何在Java中传递参数。

对于原始变量,它们按值传递。如果我没记错的话,这意味着传递了一个临时值,并且函数中对变量的任何更改都只更新临时变量。

但是,对象通过引用传递。这意味着代替整个对象,本质上是一个指向对象在内存中的位置的指针。

这意味着更新对象的变量会对该对象产生持久影响。另外,如果您将一个对象设置为等于另一个对象,那么您实际上只是将内存引用设置为相同(这样的副产品就是对象中的变量值然后被链接)。

这解释了为什么第一个功能无法完成您想要的操作(您将内存位置设置为相同)。第二个成功(你正在深层复制到一个新的内存地址)。

答案 2 :(得分:1)

理解您的问题的关键是Java的方法调用始终是按值传递,而不是通过引用。

当您致电a.copy1(b)时, Java会复制b的参考值(比如说它被称为b_copy,请注意b_copy指向与b相同的内存位置) ,然后将b_copy传递给方法copy1

copy1的方法中, Java仅更改b_copy的引用

 public void copy1(b_copy){
    b_copy=a;
 }

现在:

b_copy: b_copy=a;
b:      b does not change at all;

当方法结束时,b_copy死亡。所以b上没有任何变化!

虽然a.copy2(b)操纵对象本身,但它仍会复制b的新值(再次说b_copy)并传入copy2

 public void copy2(b_copy){
     b_copy.val = a.val;
 }

由于b_copy指向b的相同内存,所以当你对b_copy.val进行更改时,你也会在b.val本身上做同样的事情。这就是b改变的原因。

现在:

b_copy: b_copy, but b_copy's val changes
b:      b's val also changes, since b_copy is points to the b's memory location;

然后当方法结束时,b_copy死掉,b已经改变了!

您可以在Is Java "pass-by-reference" or "pass-by-value"?

上找到更多讨论

您可能还需要How do I copy an object in Java?

答案 3 :(得分:0)

你的推理是正确的。将对象传递给方法时(就像在copy1中那样),您所做的只是创建对同一对象的另一个引用。如果你覆盖这个引用,就像copy1那样,它只是意味着该引用现在指向另一个对象 - 它不会也不会改变原始对象。