IndexOutOfBoundsException - 有时只是?

时间:2011-07-11 13:53:02

标签: java loops for-loop indexing

我一直在我的程序上得到随机的java.lang.IndexOutOfBoundsException错误。 我究竟做错了什么? 该程序运行正常,它是一个非常长的循环,但对于一些元素我似乎得到该错误,然后它继续到下一个元素,它工作正常。

for (int i = 0; i < response.getSegments().getSegmentInfo().size()-1; i++) {
   reservedSeats = response.getSegments().getSegmentInfo().get(i).getCabinSummary().getCabinClass().get(i).getAmountOfResSeat();
   usedSeats = response.getSegments().getSegmentInfo().get(i).getCabinSummary().getCabinClass().get(i).getAmountOfUsedSeat();
   System.out.println("Reserved Seats: " + reservedSeats);
   System.out.println("Used Seats    : " + usedSeats);
}

如何防止此错误?

4 个答案:

答案 0 :(得分:3)

对于那些认为这是一个数组的人来说,它更像是一个列表。

让我猜,您曾经获得ConcurrentModificationExceptions,因此您重写了循环以使用元素的索引查找(避免使用迭代器)。恭喜你,你修复了异常,但没有解决问题。

在此循环运行时,您正在更改列表。每隔一段时间,你删除一个元素。你偶尔会看到最后一个元素size()-1。当操作顺序如下:

 (some thread)
 remove an element from response.getSegments().getSegmentInfo()
 (some possibly other thread)
 lookup up the size()-1 element of the above

您访问不再存在的元素,并将引发IndexOutOfBoundsException。

你需要通过控制对它的访问来修复这个List的逻辑,这样如果你需要检查所有元素,你就不会认为列表与它跨越所有元素的列表相同,或者(更好的解决方案) )冻结循环列表。

执行后者的一种简单方法是复制List(但不是列表的元素)并遍历副本。

---编辑完上面写完后在编辑中发生了显着变化的问题---

您添加了许多额外代码,包括一些额外的列表查找。您对所有列表查找使用相同的索引,但没有任何内容表明所有列表都具有相同的大小。

此外,您可能不希望跳过元素,可能您真的想要访问segmentInfo中的所有舱室类,而不仅仅是第3段信息中的第3舱类等。

答案 1 :(得分:1)

您似乎正在使用i索引到两个完全独立的List对象:

response.getSegments().getSegmentInfo().get(i) // indexing into response.getSegments().getSegmentInfo()
.getCabinSummary().getCabinClass().get(i) // indexing into getCabinSummary().getCabinClass()
.getAmountOfResSeat();

这对我来说不对。这种假设会以这种方式发生吗?并且getCabinClass()返回的列表保证至少,只要getSegmentInfo()返回的列表

答案 2 :(得分:1)

您使用i作为段信息列表的索引以及舱室类列表。这闻起来就像你问题的根源。

我不知道您的域名模型,但我希望我们在这里需要两个不同的计数器。


重构代码以显示问题(猜到了类型,替换为正确的类名)

List<SegmentInfo> segmentInfos = response.getSegments().getSegmentInfo();

for (int i = 0; i < segmentInfos.size()-1; i++) {
   // use i to get actual segmentInfo
   SegmentInfo segmentInfo = segmentInfos.get(i);
   List<CabinClass> cabinClasses = segmentInfo.getCabinSummary.getCabinClass();

   // use i again to get actual cabin class ???
   CabinClass cabinClass = cabinClasses.get(i);

   reservedSeats = cabinClass.getAmountOfResSeat();
   usedSeats = cabinClass.getAmountOfUsedSeat();

   System.out.println("Reserved Seats: " + reservedSeats);
   System.out.println("Used Seats    : " + usedSeats);
}

答案 3 :(得分:0)

假设response.getSegments().getSegmentInfo()总是返回一个大小相同的数组,在它上面调用.get(i)应该是安全的,给定循环标题(但是你知道你正在跳过最后一个元素吗?)但是,你确定.getCabinSummary()将返回一个与getSegmentInfo()数组一样大的数组吗?您使用i在两个不同的阵列中执行查找看起来很可疑。

你可以将循环体中的第一行分成两行(我只是在这里猜测类型名称):

List<SegmentInfo> segmentInfo = response.getSegments().getSegmentInfo().get(i);
reservedSeats = segmentInfo.getCabinSummary().get(i).getAmountOfResSeat();

然后你会看到哪个查找导致崩溃。