我正在尝试使用copy-contructor克隆一个对象,遗憾的是,对克隆的所有修改都反映在原始对象上。
我有这个界面
public interface Car{
public Car newInstance(Car c);
}
和各种Object hat以这种方式实现接口
public FerrariSpyder implements Car{
String name;
String description
ArrayList<Feature> featureList;
public FerrariSpyder(String name, String description, ArrayList<Feature> featureList){
this.name=name;
this.descripion=descripion;
this.featureList=featureList;
}
@Override
public Car newInstance(Car c) {
return FerrariSpyder.newInstance((FerrariSpyder) c);
}
public static FerrariSpyder newInstance(FerrariSpyder fs) {
return new FerrariSpyder(fs.getName(), fs.getDescription(), fs.getFeatureList());
}
}
现在假设我有一个名为Car
的{{1}}对象,我尝试用
originalCar
如果我在克隆的Car clone=originalCar.newIstance(originalCar);
中添加元素,featureList
中的featureList
也会被修改。
答案 0 :(得分:3)
您可以创建对象的新实例,但这些字段是共享的。
关于name
和description
,没有问题,因为Java将String
视为不可变的。如果您尝试“修改”它们,您实际上会更改对它们的引用。
关于featureList
,这是另一个故事。您当前在两个对象中都有相同的列表实例。当您调用新对象的构造函数时,需要创建列表的新实例,如下所示:
public static FerrariSpyder newInstance(FerrariSpyder fs) {
return new FerrariSpyder(fs.getName(), fs.getDescription(), new ArrayList<>(fs.getFeatureList()));
}
注意:请注意,现在有2个列表,但它们共享相同的对象。这意味着两件事:
Feature
,则会在另一个列表中看到Feature
的修改。如果您希望能够修改列表中的Feature
个对象而不影响其他列表,那么您还必须对这些对象进行深层复制。
旁注:您在此处所做的基本上是编写clone()
方法,您将其命名为newInstance()
。您应该实现Cloneable
接口以Java方式执行; - )