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

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

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

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

20 ответов


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

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

например:

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

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

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


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

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

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

вкратце:

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

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

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

ваш код следует читать:

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

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

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

int intArray[] = new int[5];

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

intArray[5];

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

какие причины ArrayIndexOutOfBoundsException?

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

создать массив такой:

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

уведомления the <, никогда не смешивайте = там..

возможно, вам захочется сделать что-то вроде этого:

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];
}

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

даже при использовании for цикл вы начали с нулевого индекса, и вы должны закончить с name.length - 1. В массиве a[n] вы можете получить доступ к форме a[0] для a[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');
}

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


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 происходит, когда вы пытаетесь получить доступ имя.индексированный элемент длины, который не существует (индекс массива заканчивается на длине -1). просто замена

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

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


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


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


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

Итак, вместо ' i**имя.длина' вы должны написать 'я


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

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

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

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

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

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

для многомерных массивов может быть сложно убедиться, что вы получаете доступ к 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 свойство того же измерения (потому что a[i].length это то же самое, что a[j].length).

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


эта ошибка возникает при цикле выполнения overlimit раз.Рассмотрим такой простой пример,

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


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

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


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

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

Если вы проверить Система.из.печать(имя.длина);

вы получите 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');
}

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

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

или такой:

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