我实现了复制构造函数,如here所述。但问题仍然是当我更新route_copy
时,相同的更新将应用于route
。所以,我不明白我的代码有什么问题?
public class Route implements Comparable<Route> {
private List<Site> sites;
public Route()
{
sites = new ArrayList<Site>();
}
public Route(List<Site> 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'
}
答案 0 :(得分:5)
在你的拷贝构造函数中,你只是做一个浅拷贝,而你需要做一个深层拷贝:
public Route(Route r) {
this(r.sites);
}
在这里,您仍在复制list
的引用,该引用仍然指向相同的ArrayList
。您应该修改它以创建列表的副本。可能,您还需要在arraylist中创建元素的副本,如下所示:
public Route(Route r) {
List<Site> newSites = new ArrayList<Site>();
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;
}
查看此帖子 - Shallow Copy vs Deep Copy.
答案 1 :(得分:2)
你的&#34;复制构造函数&#34;没有制作输入列表的副本。尝试像
这样的东西public Route(List<Site> sites)
{
this.sites = new ArrayList<Site>(sites);
}
为你的第二个构造函数。
答案 2 :(得分:2)
当然,它会创建依赖副本,也称为浅副本。
您需要深度副本。
答案 3 :(得分:2)
问题是两个列表仍然指向相同的内存位置,因此,一个列表上的任何操作最终都会修改另一个列表。
您可以尝试使用ArrayList的复制构造函数:
public ArrayList(Collection c)
构造一个列表 包含指定集合的元素,按顺序排列 由集合的迭代器返回。
像这样:
public Route(Route r) {
this(new ArrayList<Site>(r.sites));
}
但是请注意,对列表中的Site
个对象进行任何修改可能会对其他列表中存储的其他对象产生重复,具体取决于Site
对象的复杂程度。
答案 4 :(得分:1)
你使用复制构造函数做的只是让新Route
使用旧Route
的列表,因此对其中一个的任何更改都会立即影响另一个
您需要做的是让复制构造函数创建一个新列表:
sites = new ArrayList<Site>(oldList);