Что вызывает исключение java.lang.ArrayIndexOutOfBoundsException и как его предотвратить?

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

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

String[] name = { "tom", "dick", "harry" };
for (int i = 0; i <= name.length; i++) {
    System.out.println(name[i]);
}
+251
05 апр. '11 в 15:54
источник поделиться
25 ответов

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

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

Итак, например:

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

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

Одна проблема, с которой иногда сталкиваются люди, - это то, что массивы 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, сделайте это.)

+258
05 апр. '11 в 15:57
источник

Связанные вопросы


Похожие вопросы

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++) {
+47
05 апр. '11 в 15:59
источник

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

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

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

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

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

for (int i = 0; i < name.length; i++) 
                  ^
+19
05 апр. '11 в 16:15
источник

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

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

int intArray[] = new int[5];

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

intArray[5];
+15
05 апр. '11 в 15:55
источник

Чтобы исключить исключение из строя индекса массива, следует использовать 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");
}
+10
16 окт. '15 в 21:45
источник

Что вызывает 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
19 янв. '16 в 16:55
источник

В вашем коде вы получили доступ к элементам от индекса 0 до длины строкового массива. name.length дает количество строковых объектов в вашем массиве строковых объектов, то есть 3, но вы можете получить доступ только до индекса 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');
}
+5
21 июн. '17 в 4:57
источник

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

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

+4
16 янв. '18 в 12:13
источник

Вы получаете 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
06 мар. '17 в 9:00
источник

Так много для этого простого вопроса, но я просто хотел выделить новую функцию на Java, которая позволит избежать всех путаниц в индексировании в массивах даже для новичков. Java-8 абстрагировала задачу итерации для вас.

int[] array = new int[5];

//If you need just the items
Arrays.stream(array).forEach(item -> { println(item); });

//If you need the index as well
IntStream.range(0, array.length).forEach(index -> { println(array[index]); })

Какая польза? Ну, с одной стороны, это читаемость, как английский. Во-вторых, вам не нужно беспокоиться о ArrayIndexOutOfBoundsException

+3
25 окт. '17 в 7:38
источник

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: вне пределов;

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

+3
08 мар. '17 в 12:56
источник

ArrayIndexOutOfBounds означает, что вы пытаетесь проиндексировать позицию в массиве, который не выделен.

В этом случае:

String[] name = { "tom", "dick", "harry" };
for (int i = 0; i <= name.length; i++) {
    System.out.println(name[i]);
}
  • name.length равен 3, так как массив был определен с 3 объектами String.
  • При доступе к содержимому массива позиция начинается с 0. Так как есть 3 элемента, это будет означать name [0] = "tom", name [1] = "dick" и name [2] = "harry
  • Когда вы зацикливаетесь, так как я могу быть меньше или равен name.length, вы пытаетесь получить доступ к имени [3], которое недоступно.

Чтобы обойти это...

  • В вашем цикле for вы можете сделать я <name.length. Это предотвратит зацикливание на имени [3] и остановит на имени [2]

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

  • Используйте для каждого цикла

    String[] name = { "tom", "dick", "harry" }; for(String n: name) { System.out.println(n); }

  • Используйте list.forEach(Consumer action) (требуется Java8)

    String[] name = { "tom", "dick", "harry" }; Arrays.asList(name).forEach(System.out::println);

  • Конвертировать массив в поток - это хороший вариант, если вы хотите выполнить дополнительные "операции" с вашим массивом, например, фильтровать, преобразовывать текст, конвертировать в карту и т.д. (Требуется Java8)

    String[] name = { "tom", "dick", "harry" }; --- Arrays.asList(name).stream().forEach(System.out::println); --- Stream.of(name).forEach(System.out::println);

+2
14 дек. '18 в 0:08
источник

Наиболее распространенный случай, который я видел для кажущихся таинственными ArrayIndexOutOfBoundsExceptions, то есть, по-видимому, не вызванных вашим собственным кодом обработки массива, является одновременным использованием SimpleDateFormat. В частности, в сервлете или контроллере:

public class MyController {
  SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");

  public void handleRequest(ServletRequest req, ServletResponse res) {
    Date date = dateFormat.parse(req.getParameter("date"));
  }
}

Если два потока вступают в метод SimplateDateFormat.parse(), вы, скорее всего, увидите исключение ArrayIndexOutOfBoundsException. Обратите внимание на раздел синхронизации класса javadoc для SimpleDateFormat.

Удостоверьтесь, что в вашем коде нет места, которое будет обращаться к небезопасным классам потоков, таким как SimpleDateFormat, одновременно, как в сервлете или контроллере. Проверьте все переменные экземпляра ваших сервлетов и контроллеров для вероятных подозреваемых.

+2
05 апр. '11 в 16:06
источник

Для многомерных массивов может быть сложно получить доступ к свойству length правого измерения. Возьмем следующий код, например:

int [][][] a  = new int [2][3][4];

for(int i = 0; i < a.length; i++){
    for(int j = 0; j < a[i].length; j++){
        for(int k = 0; k < a[j].length; k++){
            System.out.print(a[i][j][k]);
        }
        System.out.println();
    }
    System.out.println();
}

Каждое измерение имеет разную длину, поэтому тонкая ошибка заключается в том, что средняя и внутренняя циклы используют свойство length того же размера (поскольку length a[i].length той же a[j].length).

Вместо этого для простоты внутренний цикл должен использовать a[i][j].length (или a[0][0].length).

+2
12 июн. '18 в 19:41
источник

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

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

+2
15 сент. '18 в 10:29
источник

ArrayIndexOutOfBoundsException означает, что вы пытаетесь получить доступ к индексу массива, который не существует или не связан с границей этого массива. Индексы массивов начинаются с 0 и заканчиваются на длина - 1.

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

for(int i = 0; i<=name.length; i++) {
    System.out.print(name[i] +'\n'); // i goes from 0 to length, Not correct
}

ArrayIndexOutOfBoundsException происходит, когда вы пытаетесь получить доступ индексированный элемент name.length, который не существует (индекс массива заканчивается на -1). просто заменяя <= с < решит эту проблему.

for(int i = 0; i < name.length; i++) {
    System.out.print(name[i] +'\n');  // i goes from 0 to length - 1, Correct
}
+1
30 нояб. '17 в 16:41
источник

Каждый элемент в массиве называется элементом, и каждый элемент получает доступ к его числовому индексу. Как показано на предыдущей иллюстрации, нумерация начинается с 0. Таким образом, к девятому элементу, например, следует обращаться по индексу 8.

IndexOutOfBoundsException выводится, чтобы указать, что индекс какого-либо типа (например, массив, строка или вектор) выходит за пределы диапазона.

К любому массиву X можно получить доступ с [0 до (X.length - 1)]

+1
18 окт. '18 в 9:24
источник

Я вижу все ответы здесь, объясняющие, как работать с массивами и как избегать исключений индекса за пределами границ. Я лично избегаю массивов любой ценой. Я использую классы Collections, что исключает всю глупость необходимости полностью разбираться с индексами массивов. Циклические конструкции прекрасно работают с коллекциями, поддерживающими код, который легче писать, понимать и поддерживать.

+1
13 нояб. '18 в 18:08
источник

Для любого массива длины n элементы массива будут иметь индекс от 0 до n-1.

Если ваша программа пытается получить доступ к любому элементу (или памяти) с индексом массива, большим, чем n-1, тогда Java будет вызывать ArrayIndexOutOfBoundsException

Итак, вот два решения, которые мы можем использовать в программе

  1. Поддержание счета:

    for(int count = 0; count < array.length; count++) {
        System.out.println(array[count]);
    }
    

    Или какой-нибудь другой оператор цикла, например

    int count = 0;
    while(count < array.length) {
        System.out.println(array[count]);
        count++;
    }
    
  2. Лучший способ пойти с a для каждого цикла, в этом методе программисту не нужно беспокоиться о количестве элементов в массиве.

    for(String str : array) {
        System.out.println(str);
    }
    
+1
11 нояб. '16 в 8:21
источник

Согласно вашему Коду:

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

Если вы проверите System.out.print(name.length);

вы получите 3;

это означает, что длина вашего имени равна 3

ваш цикл работает от 0 до 3, который должен работать либо от "0 до 2", либо от "1 до 3",

Ответ

String[] name = {"tom", "dick", "harry"};
for(int i = 0; i<name.length; i++) {
  System.out.print(name[i] +'\n');
}
+1
26 мар. '18 в 8:08
источник

Имя ArrayIndexOutOfBoundsException объясняет, что если вы пытаетесь получить доступ к значению в индексе, который выходит за пределы массива Array, возникает такое исключение.

В вашем случае вы можете просто удалить знак равенства из цикла for.

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

Лучшим вариантом является итерация массива:

for(String i : name )
      System.out.println(i);
0
17 мая '18 в 3:27
источник

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

0
12 апр. '19 в 2:43
источник

Эта ошибка возникает при переполнении циклов цикла. Давайте рассмотрим простой пример, например,

class demo{
  public static void main(String a[]){

    int[] numberArray={4,8,2,3,89,5};

    int i;

    for(i=0;i<numberArray.length;i++){
        System.out.print(numberArray[i+1]+"  ");
    }
}

Сначала я инициализировал массив как "numberArray". то некоторые элементы массива печатаются с использованием цикла. Когда цикл запускает время "i", напечатайте элемент (numberArray [i + 1].. (когда значение я равно 1, будет напечатан элемент numberArray [i + 1].) Предположим, что, когда я = (numberArray. length-2), последний элемент массива печатается. Когда значение "i" переходит к (numberArray.length-1), нет значения для печати. В этот момент происходит "ArrayIndexOutOfBoundsException". Я надеюсь, что вы можете получить idea.thank вас!

0
17 июл. '18 в 3:03
источник

Вы не могли перебирать или хранить больше данных, чем длина вашего массива. В этом случае вы можете сделать следующее:

for (int i = 0; i <= name.length - 1; i++) {
    // ....
}

Или это:

for (int i = 0; i < name.length; i++) {
    // ...
}
-3
19 янв. '16 в 16:26
источник

В этом разделе вы получаете доступ к элементам вне цикла:

for(int i=0; i<list.size; i++)
{

}

В этом случае цикл цикла For завершен, и вы снова получаете значение из списка с помощью i++: для получения ArrayindexOutOfBoundexception.

Было бы лучше пойти с циклом ForEach - где все эти проблемы будут заботиться:

for(String str : list)
{
}
-6
02 дек. '17 в 17:18

Посмотрите другие вопросы по меткам или Задайте вопрос