Как исправить ошибку: java.lang.ArrayIndexOutOfBoundsException [duplicate]

В следующем примере, который я написал, показано, как

  • обрабатывать асинхронные HTTP-вызовы;
  • Подождать ответа от каждого вызова API;
  • Использовать шаблон promise ;
  • Используйте шаблон Promise.All для объединения нескольких HTTP-вызовов;

Этот рабочий пример является автономным. Он будет определять простой объект запроса, который использует объект window XMLHttpRequest для совершения вызовов. Он будет определять простую функцию, чтобы дождаться завершения кучи обещаний.

Контекст. В этом примере запрашивается конечная точка Spotify Web API для поиска объектов playlist для заданного набора строк запроса:

[
 "search?type=playlist&q=%22doom%20metal%22",
 "search?type=playlist&q=Adele"
]

Для каждого элемента новый Promise запустит блок - ExecutionBlock, проанализирует результат, заплатит новый набор обещаний на основе массива результатов, который представляет собой список объектов Spotify user и выполняет новый HTTP-вызов в ExecutionProfileBlock асинхронно.

Затем вы можете увидеть вложенную структуру Promise, которая позволяет вам генерировать множественные и полностью асинхронные вложенные HTTP-вызовы и присоединять результаты к каждому подмножеству вызовов через Promise.all.

NOTE Recent Spotify search API-интерфейсам потребуется указать токен доступа в заголовках запроса:

-H "Authorization: Bearer {your access token}" 

Итак, вы должны запустить следующий пример, вам нужно поместить маркер доступа в заголовки запроса:

var spotifyAccessToken = "YourSpotifyAccessToken";
var console = {
    log: function(s) {
        document.getElementById("console").innerHTML += s + "
" } } // Simple XMLHttpRequest // based on https://davidwalsh.name/xmlhttprequest SimpleRequest = { call: function(what, response) { var request; if (window.XMLHttpRequest) { // Mozilla, Safari, ... request = new XMLHttpRequest(); } else if (window.ActiveXObject) { // Internet Explorer try { request = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { try { request = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {} } } // State changes request.onreadystatechange = function() { if (request.readyState === 4) { // Done if (request.status === 200) { // Complete response(request.responseText) } else response(); } } request.open('GET', what, true); request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken); request.send(null); } } //PromiseAll var promiseAll = function(items, block, done, fail) { var self = this; var promises = [], index = 0; items.forEach(function(item) { promises.push(function(item, i) { return new Promise(function(resolve, reject) { if (block) { block.apply(this, [item, index, resolve, reject]); } }); }(item, ++index)) }); Promise.all(promises).then(function AcceptHandler(results) { if (done) done(results); }, function ErrorHandler(error) { if (fail) fail(error); }); }; //promiseAll // LP: deferred execution block var ExecutionBlock = function(item, index, resolve, reject) { var url = "https://api.spotify.com/v1/" url += item; console.log( url ) SimpleRequest.call(url, function(result) { if (result) { var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) { return item.owner.href; }) resolve(profileUrls); } else { reject(new Error("call error")); } }) } arr = [ "search?type=playlist&q=%22doom%20metal%22", "search?type=playlist&q=Adele" ] promiseAll(arr, function(item, index, resolve, reject) { console.log("Making request [" + index + "]") ExecutionBlock(item, index, resolve, reject); }, function(results) { // Aggregated results console.log("All profiles received " + results.length); //console.log(JSON.stringify(results[0], null, 2)); ///// promiseall again var ExecutionProfileBlock = function(item, index, resolve, reject) { SimpleRequest.call(item, function(result) { if (result) { var obj = JSON.parse(result); resolve({ name: obj.display_name, followers: obj.followers.total, url: obj.href }); } //result }) } //ExecutionProfileBlock promiseAll(results[0], function(item, index, resolve, reject) { //console.log("Making request [" + index + "] " + item) ExecutionProfileBlock(item, index, resolve, reject); }, function(results) { // aggregated results console.log("All response received " + results.length); console.log(JSON.stringify(results, null, 2)); } , function(error) { // Error console.log(error); }) ///// }, function(error) { // Error console.log(error); });

Я подробно рассмотрел это решение здесь .

206
задан Infinite Recursion 20 October 2014 в 10:13
поделиться

14 ответов

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

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

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

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

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

214
ответ дан Makoto 25 August 2018 в 07:53
поделиться

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

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
ответ дан Abhishek Agarwal 25 August 2018 в 07:53
поделиться

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

for(int i = 0; i < name.length; i++) {
    System.out.print(name[i] +'\n');  // i goes from 0 to length - 1, Correct
}
1
ответ дан adn.911 25 August 2018 в 07:53
поделиться
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++) {
39
ответ дан BalusC 25 August 2018 в 07:53
поделиться

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

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

0
ответ дан Bill the Lizard 25 August 2018 в 07:53
поделиться
0
ответ дан GT_hash 25 August 2018 в 07:53
поделиться

Чтобы исключить исключительное исключение индекса массива, следует использовать инструкцию расширенный- 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
ответ дан Lundin 25 August 2018 в 07:53
поделиться

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

Итак, вместо 'i ** & lt; = name.length' вы должны написать 'i & lt; ** name.length' чтобы избежать «ArrayIndexOutOfBoundsException».

1
ответ дан nIKHIL 25 August 2018 в 07:53
поделиться

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

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

int intArray[] = new int[5];

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

intArray[5];
11
ответ дан Octavian Damiean 25 August 2018 в 07:53
поделиться

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

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

Или это:

for (int i = 0; i < name.length; i++) {
    // ...
}
3
ответ дан Peter Mortensen 25 August 2018 в 07:53
поделиться

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

1
ответ дан Satyendra Kumar 25 August 2018 в 07:53
поделиться

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

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

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

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

for(String i : name )
      System.out.println(i);
0
ответ дан Stephen Rauch 25 August 2018 в 07:53
поделиться

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

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

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

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

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

for(int i = 0; i < name.length; i++) 
                 ^
16
ответ дан Teepeemm 25 August 2018 в 07:53
поделиться

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

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

Создание такого массива:

final int[] myArray = new int[5]

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

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

myArray[3]

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

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, необходимо рассмотреть некоторые ключевые моменты:

Looping

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

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). Единственное место, которое должно изменить значение, это сохранить цикл. Изменение в противном случае просто рискует исключением и в большинстве случаев не является обязательным.

Retrieval / update

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

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];
}
6
ответ дан Tobb 25 August 2018 в 07:53
поделиться
Другие вопросы по тегам:

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