我有一个包含Arraylists的ArrayList,这是代码:
ArrayList<ArrayList<String>> results = new ArrayList<ArrayList<String>>();
ArrayList<String> row = new ArrayList<String>();
我想要的是results
ArrayList包含row
ArrayList。我认为在向ArrayList添加内容之后,它将被硬编码到该ArrayList中。但是看起来ArrayList的内容仍然与我添加到它的变量的内容有关,因为当我运行这段代码时:
row.add("ROW 1 ITEM 1");
row.add("ROW 1 ITEM 2");
row.add("ROW 1 ITEM 3");
row.add("ROW 1 ITEM 4");
row.add("ROW 1 ITEM 5");
row.add("ROW 1 ITEM 6");
results.add(row);
row.clear();
log(results.toString());
控制台中记录的结果是[[]]。我有什么方法可以这样使用它吗?
答案 0 :(得分:2)
是的,Java使用引用。如果您在引用clear
的引用上调用ArrayList
,则引用完全相同内存的其他引用将看到相同的内容。 ArrayList
为空。
如果要保留内容,请将其保存到其他ArrayList
实例。
答案 1 :(得分:2)
这是因为Java使用引用而不是复杂数据类型的克隆/副本(非复杂类型为int
,char
和类似)。
在你的情况下,这意味着ArrayList<String> row
在内存中获得一些位置并存储在那里
如果您现在通过row
直接将result
添加到result.add(row);
,只需在内存中row
的原始位置添加引用(或C ++中的指针)ArrayList result
}。
所以这意味着如果您更改row
中的任何内容,它也会在result
中更改,因为两个对象都会在内存中引用相同的位置并进行修改。
要解决此问题,每次要添加row
副本时都必须创建一个新副本,该副本引用内存中的其他位置,然后将副本添加到结果中。
1.方式:
创建一个这样的方法:
ArrayList<String> createCopy (ArrayList<String> orginal) {
ArrayList<String> copy = new ArrayList<String>()
for (String s:orginal) {
copy.add(s);
}
return copy;
}
2。方法:
查找您最喜欢的方法如何在java中创建ojbects的深层克隆/副本并使用它。
答案 2 :(得分:1)
您正在将ArrayList行的引用添加到结果中。一旦调用row.clear(),将删除所有元素。您可以在清除之前记录,或者不添加引用创建新的ArrayList并深度复制列表。
答案 3 :(得分:0)
是的,这不起作用,因为您在打印之前删除行ArrayList。除非您将内容复制到结果ArrayList,否则将删除该数据,因为我相信在调用.toString()方法时引用了行ArrayList
答案 4 :(得分:0)
那是因为数组列表中的内容aréobject'a引用,所以你有两个引用指向行,一个是变量行,另一个引用是数组结果的第一个元素,如果你改变了对象使用行引用(变量),它将影响arraylist结果中的arraylist
答案 5 :(得分:0)
您可以根据内存如何分配给Java中的对象来理解这一点。
最初,您只有一个 row
Arraylist,并且您将该ArrayList添加到 results
Arraylist。
您需要了解这一点,实例化/分配内存只有一个 row
的ArrayList,以及 results
ArrayList仅包含 row
对象, NOT 任何新对象。
因此,当您删除 row
时,该对象将被删除。
由于内存中只有一个对象,删除后输出为空。