复制构造函数创建依赖副本

我实现了这里描述的复制构造函数。 但问题仍然是当我更新route_copy ,相同的更新将应用于route 。 所以,我不明白我的代码有什么问题?

 public class Route implements Comparable { private List sites; public Route() { sites = new ArrayList(); } public Route(List sites) { this.sites = sites; } /** * Copy constructor */ public Route(Route r) { this(r.sites); } public void deleteSite(Site s) { this.sites.remove(s); } } public processData(Route route) { Route route_copy = new Route(route); Site s = selectSite(route_copy); route_copy.deleteSite(s); // !!! now 'route' does not contain an element 's' } 

在你的拷贝构造函数中,你只是做一个浅拷贝,而你需要做一个深拷贝:

 public Route(Route r) { this(r.sites); } 

在这里,您仍在复制list的引用,该引用仍指向相同的ArrayList 。 您应该修改它以创建列表的副本。 可能,您还需要在arraylist中创建元素的副本,如下所示:

 public Route(Route r) { List newSites = new ArrayList(); for (Site obj: r.sites) { // Add copy of obj to the newSites // So you need yet another copy constructor in 'Site' class. } this.sites = newSites; } 

查看此post – 浅拷贝与深拷贝。

您的“复制构造函数”未复制输入列表。 尝试类似的东西

 public Route(List sites) { this.sites = new ArrayList(sites); } 

为你的第二个构造函数。

当然它会创建依赖拷贝,也称为拷贝。

您需要一份Deep副本。

问题是两个列表仍指向相同的内存位置,因此,一个列表上的任何操作最终都会修改另一个列表。

您可以尝试使用ArrayList的复制构造函数:

public ArrayList(Collection c)

按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表。

像这样:

  public Route(Route r) { this(new ArrayList(r.sites)); } 

但请注意,对列表中的Site对象进行任何修改可能会对存储在另一个列表中的其他对象进行重新调整,具体取决于Site对象的复杂程度。

你使用复制构造函数做的只是让新的Route使用旧Route的列表,因此对其中一个的任何更改立即影响另一个

你需要做的是让复制构造函数创建一个新列表:

 sites = new ArrayList(oldList);