无法使用复制构造函数正确实例化新对象克隆

时间:2014-04-23 15:22:30

标签: java android

我正在尝试使用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也会被修改。

1 个答案:

答案 0 :(得分:3)

您可以创建对象的新实例,但这些字段是共享的。

关于namedescription,没有问题,因为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方式执行; - )