0

我有这个:

import java.util.ArrayList;


public class MyClass {
    ArrayList list = new ArrayList();

    public MyClass(){

    }

    public MyClass(MyClass aClass){
        this.list = aClass.getList();
    }

    public void add(int number){
        list.add(number);
    }

    public void set(int number){
        list.set(0, number);
    }

    public int get(){
        return (Integer)list.get(0);
    }

    public ArrayList getList(){
        return list;
    }
}



MyClass aName = new MyClass();
aName.add(5);
System.out.println("aName: "+aName.get());

MyClass aName2 = new MyClass(aName);
System.out.println("aName2: "+aName2.get());

aName2.set(1);
System.out.println("aName2: "+aName2.get());
System.out.println("aName: "+aName.get());

这将打印: aName: 5 aName2: 5 aName2: 1 aName: 1

我不希望我的第二个对象更改我的第一个对象中的值。有什么方法可以阻止这种情况的发生,但仍然能够从另一个对象复制属性?

4

4 回答 4

1

然后不要将列表从原始对象传递给新对象,在

public MyClass(MyClass aClass){ 
    this.list = aClass.getList(); 
} 

它使两个对象都具有对同一个列表的引用(两个对象之间仅共享一个列表)。

你应该做

public MyClass(MyClass aClass){ 
    this.list = (List) aClass.getList().clone(); 
} 
于 2012-07-26T19:39:06.450 回答
1

是的,你可以阻止它。您需要在复制构造函数中制作列表的防御性副本

public MyClass(MyClass aClass){
    this.list = new ArrayList(aClass.getList());
}

您可以使用clone(),但正如 Josh Bloch 在 Effective Java 项目中所说的那样,“复制构造函数有很多优势clone” - 它们在实践中更可取。

于 2012-07-26T19:39:16.780 回答
1

您可以 clone() 或获取副本,但由于您已经创建了一个列表,而不是丢弃它,您可以使用它。;)

public MyClass(MyClass aClass){
    this.list.addAll(aClass.getList());
}
于 2012-07-26T19:41:24.830 回答
0

您正在将参考值复制到ArrayList新对象中。您现在有两个对同一个列表的引用。

ArrayList构建第二个对象时需要创建一个新对象:

public MyClass(MyClass aClass){
    this.list = new ArrayList(aClass.getList());
}

但是请注意,现在两个列表都包含相同的对象。同样,这只会创建一个新列表并复制原始列表中对象的引用值。如果您需要两个包含唯一对象的完整且单独的列表,则需要编写一个进行深拷贝的方法,同时复制列表中的对象。

于 2012-07-26T19:44:07.010 回答