Что вызывает исключение java.lang.ArrayIndexOutOfBoundsException и как его предотвратить? - PullRequest
264 голосов
/ 05 апреля 2011

Что означает ArrayIndexOutOfBoundsException и как от него избавиться?

Вот пример кода, который вызывает исключение:

String[] name = { "tom", "dick", "harry" };
for (int i = 0; i <= name.length; i++) {
    System.out.println(name[i]);
}

Ответы [ 24 ]

267 голосов
/ 05 апреля 2011

Ваш первый порт захода должен быть документация , которая объясняет это достаточно ясно:

Брошенный, чтобы указать, что к массиву обращались с недопустимым индексом. Индекс либо отрицательный, либо больше или равен размеру массива.

Так, например:

int[] array = new int[5];
int boom = array[10]; // Throws the exception

Что касается того, как этого избежать ... хм, не делай этого. Будьте осторожны с вашими индексами массива.

Одна проблема, с которой иногда сталкиваются люди, - это думать, что массивы индексируются 1, например,

int[] array = new int[5];
// ... populate the array here ...
for (int index = 1; index <= array.length; index++)
{
    System.out.println(array[index]);
}

Это упустит первый элемент (индекс 0) и выдаст исключение, когда индекс равен 5. Допустимые индексы здесь 0-4 включительно. Правильное идиоматическое выражение for здесь будет:

for (int index = 0; index < array.length; index++)

(Предполагается, что нужен индекс, конечно. Если вы вместо этого можете использовать расширенный цикл for, сделайте это.)

48 голосов
/ 05 апреля 2011
if (index < 0 || index >= array.length) {
    // Don't use this index. This is out of bounds (borders, limits, whatever).
} else {
    // Yes, you can safely use this index. The index is present in the array.
    Object element = array[index];
}

См. Также:


Обновление : согласно вашему фрагменту кода,

for (int i = 0; i<=name.length; i++) {

Индекс включает длину массива.Это за пределами.Вам нужно заменить <= на <.

for (int i = 0; i < name.length; i++) {
20 голосов
/ 05 апреля 2011

Короче говоря:

В последней итерации

for (int i = 0; i <= name.length; i++) {

i будет равно name.length, что является недопустимым индексом, поскольку индексы массива начинаются с нуля.

Ваш код должен читать

for (int i = 0; i < name.length; i++) 
                  ^
16 голосов
/ 05 апреля 2011

Это означает, что вы пытаетесь получить доступ к индексу массива, который недопустим, поскольку он не находится между границами.

Например, это инициализирует массив целых примитивов с верхней границей 4.

int intArray[] = new int[5];

Программисты считают с нуля. Так что это, например, выдаст ArrayIndexOutOfBoundsException, поскольку верхняя граница равна 4, а не 5.

intArray[5];
10 голосов
/ 19 января 2016

Что вызывает ArrayIndexOutOfBoundsException?

Если вы рассматриваете переменную как «ящик», в который можно поместить значение, тогда массив представляет собой серию блоков, расположенных рядом сeachother, где число ячеек является конечным и явным целым числом.

Создание массива следующим образом:

final int[] myArray = new int[5]

создает строку из 5 ящиков, каждая из которых содержит int.Каждый из ящиков имеет индекс, позицию в ряду ящиков.Этот индекс начинается с 0 и заканчивается N-1, где N - размер массива (количество ящиков).

Чтобы получить одно из значений из этой серии ящиков, вы можете обратиться кэто через его индекс, как это:

myArray[3]

, который даст вам значение 4-го блока в серии (так как первый блок имеет индекс 0).

An ArrayIndexOutOfBoundsExceptionвызвано попыткой извлечь «ящик», который не существует, путем передачи индекса, который выше индекса последнего «ящика», или отрицательным.

В моем работающем примере эти фрагменты кода будут производитьтакое исключение:

myArray[5] //tries to retrieve the 6th "box" when there is only 5
myArray[-1] //just makes no sense
myArray[1337] //waay to high

Как избежать ArrayIndexOutOfBoundsException

Чтобы предотвратить ArrayIndexOutOfBoundsException, необходимо учитывать следующие ключевые моменты:

Цикл

При циклическом просмотре массива всегда проверяйте, что индекс, который вы получаете, строго меньше длины массива (количества блоков).Например:

for (int i = 0; i < myArray.length; i++) {

Обратите внимание на <, никогда не смешивайте там = ..

Возможно, вы захотите сделать что-то подобное:

for (int i = 1; i <= myArray.length; i++) {
    final int someint = myArray[i - 1]

Только не надо.Придерживайтесь приведенного выше (если вам нужно использовать указатель), и это избавит вас от боли.

По возможности используйте foreach:

for (int value : myArray) {

Таким образом, вы выиграли 'вообще не нужно думать об индексах.

При зацикливании, что бы вы ни делали, НИКОГДА не меняйте значение итератора цикла (здесь: i).Единственное место, где это должно изменить значение - это поддерживать цикл.В противном случае это просто риск для исключения, и в большинстве случаев это не обязательно.

Извлечение / обновление

При извлечении произвольного элемента массива всегда проверяйте, чтоэто допустимый индекс для длины массива:

public Integer getArrayElement(final int index) {
    if (index < 0 || index >= myArray.length) {
        return null; //although I would much prefer an actual exception being thrown when this happens.
    }
    return myArray[index];
}
10 голосов
/ 17 октября 2015

Чтобы избежать исключения за пределами индекса массива, следует использовать оператор extended- for, где и когда они могут.

Основная мотивация (и вариант использования) - это когда вы выполняете итерацию и вам не требуются какие-либо сложные шаги итерации.Вы бы не могли бы использовать расширенный for для перемещения назад в массиве или выполнять итерации только для каждого другого элемента.

Вы гарантированно не исчерпаете элементы дляитерируйте при этом, и ваш [исправленный] пример легко преобразуется.

Код ниже:

String[] name = {"tom", "dick", "harry"};
for(int i = 0; i< name.length; i++) {
    System.out.print(name[i] + "\n");
}

... эквивалентен этому:

String[] name = {"tom", "dick", "harry"};
for(String firstName : name) {
    System.out.println(firstName + "\n");
}
5 голосов
/ 21 июня 2017

В вашем коде вы получили доступ к элементам от индекса 0 до длины массива строк. name.length дает количество строковых объектов в вашем массиве строковых объектов, то есть 3, но вы можете получить доступ только до индекса 2 name[2], потому что к массиву можно получить доступ из индекса от 0 до name.length - 1, где вы получите name.length количество объектов.

Даже при использовании цикла for вы начали с индекса ноль, и вы должны заканчивать name.length - 1. В массиве a [n] вы можете получить доступ от формы [0] к [n-1].

Например:

String[] a={"str1", "str2", "str3" ..., "strn"};

for(int i=0;i<a.length()i++)
    System.out.println(a[i]);

В вашем случае:

String[] name = {"tom", "dick", "harry"};

for(int i = 0; i<=name.length; i++) {
    System.out.print(name[i] +'\n');
}
4 голосов
/ 16 января 2018

Для вашего данного массива длина массива равна 3 (т.е. name.length = 3). Но поскольку он хранит элемент, начиная с индекса 0, он имеет максимальный индекс 2.

Итак, вместо «i ** <= <strong>name.length» вы должны написать «i <** name.length», чтобы избежать «ArrayIndexOutOfBoundsException». </p>

3 голосов
/ 06 марта 2017

Вы получаете ArrayIndexOutOfBoundsException из-за i<=name.length части.name.length возвращает длину строки name, которая равна 3. Следовательно, когда вы пытаетесь получить доступ к name[3], это недопустимо и выдает исключение.

Разрешенный код:

String[] name = {"tom", "dick", "harry"};
for(int i = 0; i < name.length; i++) { //use < insteadof <=
  System.out.print(name[i] +'\n');
}

Это определено в спецификации языка Java :

Поле public final length, которое содержит количество компонентов массива.length может быть положительным или нулевым.

3 голосов
/ 08 марта 2017

Array index out of bounds exception

Вот как выглядит этот тип исключений при создании в Eclipse. Цифра красного цвета обозначает индекс, к которому вы пытались получить доступ. Таким образом, код будет выглядеть так:

myArray[5]

Ошибка выдается при попытке доступа к индексу, который не существует в этом массиве. Если массив имеет длину 3,

int[] intArray = new int[3];

тогда единственные допустимые индексы:

intArray[0]
intArray[1]
intArray[2]

Если массив имеет длину 1,

int[] intArray = new int[1];

тогда единственный действительный индекс:

intArray[0]

Любое целое число, равное длине массива или больше его: выходит за пределы.

Любое целое число меньше 0: выходит за пределы;

P.S .: Если вы хотите лучше понять массивы и выполнить некоторые практические упражнения, здесь есть видео: учебник по массивам в Java

...