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
давайте продолжим это обсуждение в чате - person mavrav; 09.03.2012
comment
Нет, спасибо. Обсуждать нечего, если только вы не пробовали использовать Collections.synchronisedList() и это не решило проблему. - person Dave Webb; 09.03.2012

Размещенный вами код будет не вызывать исключение ArrayIndexOutOfBoundsException.

Исключение, которое вы получаете, генерируется в той части, которую вы пропустили. Взгляните на свою трассировку стека. Его InboxSearchBean вызывает исключение. Скорее всего, он выполняет get(index) в списке с недопустимым индексом.

person Durandal    schedule 09.03.2012