假设我有三个列表free
,home
和tableau
,它们都包含不同的对象。我还有一个名为History
的类,它的构造函数接受所有这三个列表并创建一个新的Object。现在,我正在尝试创建一个包含所有历史对象的List<History>
。我正在添加所有<History>
对象,如下所示,
List<Hisotry> history = new ArrayList<>();
history.add(new History(free, home, tableau));
//make some changes in the lists (free, home, tableau),
//then add it again in the history list
history.add(new History(free, home, tableau));
//make some more changes again then add it
history.add(new History(free, home, tableau));
虽然它将所有对象添加到列表中,但它们都引用了同一个对象。换句话说,如果我添加3个<History>
个对象,它会打印相同的<Hisotry>
个对象3次,当它们全部应该不同时。我不确定为什么每次创建新对象并将其添加到列表时它都会添加或引用同一个对象。添加新对象时我做错了什么?
** P.S。我希望我有意义,如果没有,请随时告诉我,我会上传我的整个代码。
答案 0 :(得分:2)
您已经正确地发现History
个对象包含对相同列表的引用。因此,您有3个不同的History
个对象,但所有3个实例都“指向”相同的列表。
您可以在为新的History
对象修改列表之前克隆列表,即:
List<History> history = new ArrayList<>();
history.add(new History(free, home, tableau));
free = new ArrayList(free);
home = new ArrayList(home);
tableau = new ArrayList(tableau);
// make some changes to the lists
history.add(new History(free, home, tableau));
free = new ArrayList(free);
home = new ArrayList(home);
tableau = new ArrayList(tableau);
// make more changes to the lists
history.add(new History(free, home, tableau));
请注意,如果列表free
,home
,tableau
包含对可变对象的引用,并且这些对象可以根据您的程序逻辑进行更改,那么上面的代码就赢了工作,您还需要克隆每个列表项。
答案 1 :(得分:2)
Answer by Shesterov是正确的。
这是一个图表,用于显示问题中描述的内容。我添加了“动物”对象作为“免费” - “主页” - “画面”列表中包含的元素,因为您没有提及它们的内容。
正确的答案是提出两点:
如果你按照 Shesterov的代码并在每个历史对象的构造过程中复制每个列表,你最终会得到 12个粉色列表而不是3个:原来的3个加3个列表对于3个History对象中的每一个。所以:12 = 3 + ( 3 * 3 )
。但是你仍然拥有相同的5个Animal对象。但是,走这条路线历史“b”,例如,可以改变其“家”列表,以删除对名为Bob的鸟的引用,而原始的“主页”列表和历史“a”“主页”列表和历史记录“c “”home“列表仍然会有一个指向名为Bob的鸟的指针。
换句话说,不要将对象引用传递给Xerox机器。取而代之的是将这些物体视为纸张索引卡片,每个物体都如图所示通过一根带有透明胶带的绳子连接到卡片上。传递物体不会使卡片复制;传递一个对象用磁带附加另一个字符串。
最后一点:不要将List / Collection对象与它“包含”的元素混淆(指向)。在仓库中,您可以通过在剪贴板上列出每个箱子的ID号来清点箱子。剪贴板是一个“列表”,但它本身不是板条箱。剪贴板/清单对象是引用的集合,以完全分隔不同的其他对象,即包装箱。
答案 2 :(得分:1)
您每次都在创建新的History对象,这很好。但是你说你修改了现有的免费,家庭和画面阵列列表。这3个数组列表仍在使用相同的引用进行修改,因此您也可以在其他History对象中更新它们。