2011-07-11 50 views
0

我一直在我的程序中得到隨機java.lang.IndexOutOfBoundsException錯誤。 我在做什麼錯? 該程序運行良好,它是一個非常長的循環,但對於一些元素,我似乎正在得到該錯誤,然後它繼續到下一個元素,它工作正常。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); 
} 

如何防止此錯誤?

+6

您需要向我們展示實際執行數組查找的代碼(大概是循環體)。 –

+0

@Aasmund:添加了代碼 – jcotal

+1

IOOB異常可能發生在'.... getCabinClass()。get(i)'part?有沒有什麼能保證你可以在'getSegmentInfo()。'中使用大小? – Jacob

回答

1

你似乎使用i索引爲兩個完全獨立的List對象:

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

這看起來我錯了。這假設發生這種方式?並且是getCabinClass()返回的列表保證爲至少只要返回getSegmentInfo()

+0

你是正確的,顯然大小是不同的。所以我應該如何去獲取每個這些列表的元素? – jcotal

0

假設response.getSegments().getSegmentInfo()總是返回相同大小的數組,調用.get(i)它應該是安全的,考慮到環頭(但你是否知道,你是跳過最後一個元素?)但是,你肯定.getCabinSummary()會返回一個與getSegmentInfo()數組一樣大的數組?它看起來很可疑,您正在使用i在兩個不同的陣列中執行查找。

你可以在循環體中的第一線分成兩個單獨的線(我只在這裏猜測類型名稱):

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

然後你就會看到它查找導致崩潰。

+0

你是對的,顯然尺寸是不同的。所以我應該如何去獲取每個這些列表的元素? – jcotal

+0

@jcotal:取決於你打算做什麼。您是否想要針對每個細分市場只查看一個具體的客艙摘要?或者你想爲每個細分市場查看所有機艙摘要?在後一種情況下,您需要在第一個循環內創建一個新循環。 –

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); 
} 
+0

你是對的,顯然尺寸是不同的。所以我應該如何去獲取每個這些列表的元素? – jcotal

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的副本(但不是列表的元素)並遍歷副本。

---編輯在編輯極大地改變了上述寫後問題---

你增加了很多額外的代碼,包括一些額外的列表查找。您對所有列表查找使用相同的索引,但沒有任何內容表明所有列表的大小相同。

而且,你可能不希望跨元素跳過,賠率是你真的想訪問所有的客艙類的段信息,不只是第三cabinClass在第3段信息等

+0

很好的答案!你所有的假設都是正確的。我會嘗試你建議的複製列表:)非常感謝你! – jcotal

+0

你是對的。這兩個列表的大小是不同的。那麼你建議我做什麼?我想複製列表不起作用? – jcotal

+0

編寫一個嵌套循環。 –