为什么.clear()
即使在放入散列图之后也会破坏我的对象列表,而不是只创建该对象的新实例?
变量声明:
List<Pricing_Data> toAdd = new ArrayList<Pricing_Data>();
HashMap<String, List<Pricing_Data>> pricingMap_twelve = new HashMap<String, List<Pricing_Data>>();
按预期工作的示例:
pricingMap_twelve.put(pricing.get(y).getName(), toAdd);
toAdd = new ArrayList<Pricing_Data>();
在添加到所述hashmap之后,hashmap中的数据意外破坏示例:
pricingMap_twelve.put(pricing.get(y).getName(), toAdd);
toAdd.clear();
我猜这与我遇到的类似问题有关,当我第一次搞乱日历时,数据实际上并没有放入&#39;进入对象但是指向原始的指针?
答案 0 :(得分:2)
使用toAdd.clear
方法时,您将清除toAdd
变量列表当前引用的内容。
使用toAdd = new ArrayList<Pricing_Data>()
时,现在toAdd
变量指向到新参考。由toAdd
保存的旧引用仍将由pricingMap_twelve
存储在引用保留中。
更多信息:
答案 1 :(得分:2)
这是clear
的定义。它与new
不同。 new
创建一个新对象,并为您提供对新对象的引用。给定对象的方法clear
采用相同的对象并擦除其中的内容。
重要的是要理解将对象放在列表中不会将对象的复制放在列表中。它将引用放入列表中的该对象。变量中的引用和列表中的引用指向相同的对象,因此如果清除它,列表也指向已清除的对象。
所以你必须使用new
,而不是clear
。
答案 2 :(得分:1)
严格来说,Java中没有指针,但引用的行为方式大致相同:如果将引用对象添加到集合中,然后更改该对象,则集合中存储的项目也会发生变化。特别是,当您调用clear
时,结果将通过集合的所有引用显示,包括您可能已放置在其他集合中的任何引用。
这里有一个有用的推论是,如果要将集合添加到另一个容器中,您几乎总是希望在集合中创建一个新副本,而不是容器本身。这可以避免常见的错误:
List<List<String>> sentences = new ArrayList<List<String>>();
List<String> words = new ArrayList<String>();
// This is broken!
while (haveMoreData(myFile)) {
readNextSentence(myFile, words);
sentences.add(words);
words.clear();
}
上面的代码是错误的,因为它会尝试将同一个列表words
多次放入sentences
,并在两者之间清除它。最终会得到列表中最后一个句子的多个实例。
使用new
修复了问题:
List<List<String>> sentences = new ArrayList<List<String>>();
while (haveMoreData(myFile)) {
List<String> words = new ArrayList<String>();
readNextSentence(myFile, words);
sentences.add(words);
}
现在每次迭代都会为words
获取自己的容器,避免因重用和清除同一个集合而导致的别名问题。
答案 3 :(得分:1)
非基本类型的Java变量将引用保存到对象。传递引用并将它们分配给其他变量,数组等仅影响引用,而不影响它引用的对象。虽然它很常见,但它也松散,有时候说变量&#34;包含&#34;一个对象。
因此,当您使用Map.put()
时,您将地图引用注册到指定的键和值;存储在其他地方的引用(例如变量toAdd
)仍然引用同一个对象。
当然,在将新对象的引用分配给变量之后,该变量不再与之前引用的对象相关联。