我在java中的数据对象中有一个列表,其中包含从数据库中检索的数据,无论是多行还是单行。我从BO中检索List并将其转储到临时列表中,以便我可以迭代它以提取数据。当我在完成第一次分配后检查列表的大小时,一切都很顺利,但是当我尝试在for循环中迭代列表时,它的大小正在减小。我在列表中测试了两行数据,但在厕所中,它的大小始终是一个。有趣的是,我在很多地方已经多次使用过这种逻辑,但是在我写这篇文章的业务流程中,它表现得非常不稳定。有没有任何线索?这是一个示例代码
List temp = new ArrayList();
temp = dummyBO.getList(0) // Retrieves the List at index 0 from the BO
//Imagine the list has 2 rows of data. This prints the size as 2
System.out.println("size: "+temp.size());
System.out.println("Contents: "+temp.get(0);
System.out.println("Contents: "+temp.get(1);
//This is where the List starts behaving erratically
**for(int i=0;i<temp.size();i++){
System.out.println("size: "+temp.size()); //here the size is displayed as 1
System.out.println("Contents: "+temp.get(i); // here only the data at index 0 is shown
}**
P.S。此Java代码编写在IBM WID 6.1的代码段部分中
答案 0 :(得分:3)
你说:
我从BO中检索
List
并将其转储到临时列表中
你的片段说:
// original snippet
List temp = new ArrayList();
temp = dummyBO.getList(0);
绝对肯定地说这是不可能的,但这是一种代码气味,并且极有可能是造成问题的错误。
臭臭的部分是你创建了一个new ArrayList
,但它立刻就变成了垃圾。此代码段不会使用ArrayList
列表中的元素填充dummyBO
。它将temp
设置为引用新创建的对象,但随后它会释放该对象以完全引用其他内容。请记住,对象的=
只是Java中的引用赋值;它不能超载以做任何不同的事情。
也许你想要这样的东西:
// possible fix #1
List temp = new ArrayList(dummyBO.getList(0));
这实际上会创建一个new ArrayList
,并使用从dummyBO
获得的列表元素填充该列表。这使用ArrayList(Collection)
构造函数,它遍历Collection
并将其元素添加到列表中。
或者您也可以这样做:
// possible fix #2
List temp = new ArrayList();
temp.addAll(dummyBO.getList(0));
答案 1 :(得分:2)
我怀疑这个
temp = dummyBO.getList(0)
将引用检索到列表,而不是副本。因此无论为您提供此引用,都可以随意更改该列表。你需要采取这份清单的防御性副本吗?
答案 2 :(得分:0)
正如其他答案所说,你需要复制列表的内容。
但是你的问题比这更深刻。很明显,另一个线程正在改变列表的内容。简单地复制getList(0)
返回的列表并不可靠。复制时,另一个线程可能会更改列表!
相反,您需要更改getList(int)
方法,以便 it 创建列表的副本,和它会保持锁定以停止列表在被复制时被更改。
修改强>
可以使用复制构造函数创建列表副本;例如根据@polygenelubricants的回答使用new ArrayList(someList)
。
但是没有简单的答案来锁定列表以在复制时阻止列表被更改。这取决于访问和更新列表的其他内容......以及如何。