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

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

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

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

Ответ 1

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

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

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

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, сделайте это.)

Ответ 2

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++) {

Ответ 3

Из этой превосходной статьи: ArrayIndexOutOfBoundsException в цикле for

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

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

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

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

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

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

Ответ 4

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

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

int intArray[] = new int[5];

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

intArray[5];

Ответ 5

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

Ответ 6

Что вызывает 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];
}

Ответ 7

В вашем коде вы получили доступ к элементам от индекса 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');
}

Ответ 8

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

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

Ответ 9

Вы получаете 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 может быть положительной или нулевой.

Ответ 10

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

Ответ 11

Так много для этого простого вопроса, но я просто хотел выделить новую функцию на 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

Ответ 12

Для многомерных массивов может быть сложно получить доступ к свойству 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).

Ответ 13

Наиболее распространенный случай, который я видел для кажущихся таинственными 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, одновременно, как в сервлете или контроллере. Проверьте все переменные экземпляра ваших сервлетов и контроллеров для вероятных подозреваемых.

Ответ 14

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

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

Ответ 15

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);

Ответ 16

Для любого массива длины 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);
    }
    

Ответ 17

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
}

Ответ 18

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

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');
}

Ответ 19

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

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

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

Ответ 20

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

Ответ 21

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

Ответ 22

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

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

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

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

for(String i : name )
      System.out.println(i);

Ответ 23

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

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 вас!

Ответ 24

Вы можете использовать Optional в функциональном стиле, чтобы избежать NullPointerException и ArrayIndexOutOfBoundsException:

String[] array = new String[]{"aaa", null, "ccc"};
for (int i = 0; i < 4; i++) {
    String result = Optional.ofNullable(array.length > i ? array[i] : null)
            .map(x -> x.toUpperCase()) //some operation here
            .orElse("NO_DATA");
    System.out.println(result);
}

Выход:

AAA
NO_DATA
CCC
NO_DATA

Ответ 25

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

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

Или это:

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

Ответ 26

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

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

}

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

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

for(String str : list)
{
}