ArrayList.add хвърля ArrayIndexOutOfBoundsException

Опитвам се да добавя обект към ArrayList и неговото изхвърляне ArrayIndexOutOfBoundsException Следва кодът

private void populateInboxResultHolder(List inboxErrors){
    inboxList = new ArrayList();
    try{                
        inboxHolder = new InboxResultHolder();
        //Lots of Code
        inboxList.add(inboxHolder);
    }catch(Exception e){
        e.printStackTrace();
    }
}

И изключението е

[3/7/12 15:41:26:715 UTC] 00000045 SystemErr     R java.lang.ArrayIndexOutOfBoundsException
[3/7/12 15:41:26:721 UTC] 00000045 SystemErr     R      at java.util.ArrayList.add(ArrayList.java:378)
[3/7/12 15:41:26:721 UTC] 00000045 SystemErr     R      at com.ml.fusion.ui.common.web.bean.inbox.InboxSearchBean.populateInboxResultHolder(InboxSearchBean.java:388)    
[3/7/12 15:41:26:721 UTC] 00000045 SystemErr     R      at com.ml.fusion.ui.common.web.bean.inbox.InboxSearchBean.searchInboxErrors(InboxSearchBean.java:197)
[3/7/12 15:41:26:721 UTC] 00000045 SystemErr     R      at com.ml.fusion.ui.common.web.bean.inbox.InboxSearchBean.viewInbox(InboxSearchBean.java:207)

Но според подписа на ArrayList.add не трябва да хвърля това изключение. Моля помогнете.


person mavrav    schedule 09.03.2012    source източник
comment
Е, тъй като IndexOutOfBoundsException е RuntimeException, то може да бъде хвърлено, без да бъде споменато в сигнатурата на метода.   -  person Jerome    schedule 09.03.2012
comment
ArrayIndexOutOfBoundsException е изключение по време на изпълнение, а не проверено изключение, така че не е задължително да се показва в сигнатурата на методите, които го хвърлят.   -  person Giulio Piancastelli    schedule 09.03.2012
comment
така е. Но ако погледнете самия метод за добавяне, няма възможност това изключение да бъде хвърлено   -  person mavrav    schedule 09.03.2012


Отговори (2)


ArrayList.add() никога не трябва да хвърля ArrayIndexOutOfBoundsException, ако се използва "правилно", така че изглежда, че използвате вашия ArrayList по начин, който той не поддържа.

Трудно е да се каже само от кода, който сте публикували, но моето предположение е, че имате достъп до своя ArrayList от множество нишки.

ArrayList не е синхронизиран и следователно не е безопасен за нишки. Ако това е проблемът, можете да го коригирате, като обвиете своя List с помощта на Collections.synchronizedList().

Промяната на вашия код на следния трябва да разреши проблема:

private void populateInboxResultHolder(List inboxErrors){
    List inboxList = Collections.synchronizedList(new ArrayList());
    try{                
        inboxHolder = new InboxResultHolder();
        //Lots of Code
        inboxList.add(inboxHolder);
    }catch(Exception e){
        e.printStackTrace();
    }
}
person Dave Webb    schedule 09.03.2012
comment
Мислех под този ъгъл. Но дори и в този случай не трябва да хвърля това изключение, тъй като правим add, а не add(index,Obj). - person mavrav; 09.03.2012
comment
Ако имате достъп до ArrayList от множество нишки, без да го синхронизирате, той ще се повреди. Това, което мисля, че се случва, е, че две нишки се опитват да променят Array, което е в основата на ArrayList едновременно, така че не е правилният размер, когато една от нишките се опитва да добави нова стойност. - person Dave Webb; 09.03.2012
comment
Не трябва ли това да хвърля ConcurrentModificationException? - person mavrav; 09.03.2012
comment
Не. Ако използвате нещо извън неговия договор, поведението му става недефинирано. Това означава, че можете да очаквате да хвърли всякакви RuntimeException или да повреди вашите данни или да направи нещо изобщо. В документацията е ясно, че ArrayList не се поддържа в множество нишки, така че няма да има дефинирано поведение в този случай. - person Dave Webb; 09.03.2012
comment
Не съм сигурен за това. Предполагате ли, че е хвърлило това изключение, защото не е могло да получи друго изключение по това време? Дори ако има едновременно достъп до него, не трябва да хвърля това конкретно изключение, защото никъде не споменаваме индекса. - person mavrav; 09.03.2012
comment
Той хвърли това изключение, защото се опита да добави нещо към Array с индекс, който беше твърде голям. ArrayList съхранява своите данни в Array и поддържа размера на това Array автоматично. Но ако получите достъп до ArrayList от множество нишки едновременно, поддържащият код на Array не винаги се изпълнява в правилния ред и така получавате своя ArrayIndexOutOfBoundsException. Считайте се за късметлия, че сте получили изключение, а не просто повредени или изгубени данни. Ако осъществявате достъп до своя ArrayList от множество нишки, това определено е източникът на проблема ви. - person Dave Webb; 09.03.2012
comment
comment
Не благодаря. Няма какво да обсъждаме, освен ако не сте опитали да използвате Collections.synchronisedList() и това не е решило проблема. - person Dave Webb; 09.03.2012

Кодът, който публикувахте няма да хвърля ArrayIndexOutOfBoundsException.

Изключението, което получавате, се хвърля в частта, която сте пропуснали. Погледнете стека си. Неговият InboxSearchBean, който причинява изключението. Най-вероятно той изпълнява get(index) в списъка с невалиден индекс.

person Durandal    schedule 09.03.2012