Cosa causa un java.lang.ArrayIndexOutOfBoundsException e come posso impedirlo?


298

Cosa ArrayIndexOutOfBoundsExceptionsignifica e come posso liberarmene?

Ecco un esempio di codice che attiva l'eccezione:

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

1
In riferimento all'ultima domanda, il codice sarebbe utile. Stai accedendo alla matrice con un indice noto o devi iniziare il debug per capire come viene calcolato l'indice quando si verifica l'errore?
solo il

43
Sostituisci i <= name.lengthcon i < name.length- o meglio, scrivi un ciclo avanzato per. ( for (String aName : name) { ... })
Jean Hominal,

1
significa che vuoi ottenere un elemento dell'array che non esiste, 'i <= name.length' significa che vuoi ottenere la lunghezza dell'elemento + 1 - non esiste.
GB


Risposte:


296

Il tuo primo porto di scalo dovrebbe essere la documentazione che lo spiega ragionevolmente chiaramente:

Generato per indicare che è stato effettuato l'accesso a un array con un indice illegale. L'indice è negativo o maggiore o uguale alla dimensione dell'array.

Quindi per esempio:

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

Per quanto riguarda come evitarlo ... um, non farlo. Prestare attenzione con gli indici dell'array.

Un problema che a volte le persone incontrano è pensare che gli array siano 1-indicizzati, ad es

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

Ciò perderà il primo elemento (indice 0) e genererà un'eccezione quando l'indice è 5. Gli indici validi qui sono compresi tra 0 e 4. La forfrase corretta e idiomatica qui sarebbe:

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

(Supponendo che tu abbia bisogno dell'indice, ovviamente. Se invece puoi usare il ciclo avanzato per, fallo.)


1
Vorrei aggiungere che per gli array multidimensionali che potrebbero avere una forma arbitraria in Java, i cicli annidati dovrebbero controllare per la relativa lunghezza di sottoarray: for (int nestedIndex = 0; nestedIndex < array[outerIndex].length; nestedIndex++) { ... array[outerIndex][nestedIndex] ... }.
Andrey,

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

Guarda anche:


Aggiornamento : secondo lo snippet di codice,

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

L'indice comprende la lunghezza dell'array. Questo è fuori limite. È necessario sostituire <=con <.

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

22

Da questo eccellente articolo: ArrayIndexOutOfBoundsException in for loop

Per dirla brevemente:

Nell'ultima iterazione di

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

isarà uguale a name.lengthun indice illegale, poiché gli indici di array sono a base zero.

Il tuo codice dovrebbe essere letto

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

17

Significa che stai tentando di accedere a un indice di un array che non è valido in quanto non è compreso tra i limiti.

Ad esempio, questo inizializzerebbe un array di numeri interi primitivi con il limite superiore 4.

int intArray[] = new int[5];

I programmatori contano da zero. Quindi, ad esempio, questo lancerebbe un ArrayIndexOutOfBoundsExceptiondato che il limite superiore è 4 e non 5.

intArray[5];

4
I limiti sono i limiti nel raggio d'azione. ie; 0-5
John Giotta,

11

Per evitare un'eccezione fuori limite dell'indice di array, si dovrebbe usare l' istruzione avanzatafor dove e quando possono.

La motivazione principale (e il caso d'uso) è quando stai iterando e non hai bisogno di complicate fasi di iterazione. Si potrebbe non essere in grado di utilizzare un enhanced- forper spostarsi indietro in un array oppure solo iterare su ogni altro elemento.

Ti garantiamo di non rimanere senza elementi su cui scorrere durante questa operazione e il tuo esempio [corretto] viene facilmente convertito.

Il codice seguente:

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

... è equivalente a questo:

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

11

Quali sono le cause ArrayIndexOutOfBoundsException?

Se si considera una variabile come una "casella" in cui è possibile posizionare un valore, una matrice è una serie di caselle poste una accanto all'altra, in cui il numero di caselle è un numero intero finito ed esplicito.

Creazione di un array come questo:

final int[] myArray = new int[5]

crea una riga di 5 caselle, ognuna contenente un int. Ciascuna delle caselle ha un indice, una posizione nella serie di caselle. Questo indice inizia da 0 e termina in N-1, dove N è la dimensione dell'array (il numero di caselle).

Per recuperare uno dei valori da questa serie di caselle, puoi fare riferimento ad esso attraverso il suo indice, in questo modo:

myArray[3]

Il che ti darà il valore della quarta casella della serie (poiché la prima casella ha un indice 0).

Un ArrayIndexOutOfBoundsExceptionè causato dal tentativo di recuperare una "scatola" che non esiste, passando un indice che è superiore all'indice dell'ultima "scatola", o negativo.

Con il mio esempio corrente, questi frammenti di codice genererebbero tale eccezione:

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

Come evitare ArrayIndexOutOfBoundsException

Per prevenire ArrayIndexOutOfBoundsException, ci sono alcuni punti chiave da considerare:

looping

Quando si esegue il ciclo in un array, assicurarsi sempre che l'indice che si sta recuperando sia strettamente più piccolo della lunghezza dell'array (il numero di caselle). Per esempio:

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

Notare il <, mai mescolare un =dentro ..

Potresti essere tentato di fare qualcosa del genere:

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

Non farlo. Attenersi a quello sopra (se è necessario utilizzare l'indice) e ti farà risparmiare molto dolore.

Ove possibile, utilizzare foreach:

for (int value : myArray) {

In questo modo non dovrai assolutamente pensare agli indici.

Durante il loop, qualunque cosa tu faccia, MAI cambiare il valore dell'iteratore di loop (qui:) i. L'unico posto in cui ciò dovrebbe cambiare valore è quello di mantenere il ciclo attivo. Altrimenti cambiarlo è solo rischiare un'eccezione, e nella maggior parte dei casi non è necessario.

Retrieval / aggiornamento

Quando si recupera un elemento arbitrario dell'array, verificare sempre che sia un indice valido rispetto alla lunghezza dell'array:

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

Nel tuo codice hai effettuato l'accesso agli elementi dall'indice 0 alla lunghezza dell'array di stringhe. name.lengthfornisce il numero di oggetti stringa nell'array di oggetti stringa, ovvero 3, ma è possibile accedere solo all'indice 2 name[2], poiché è possibile accedere all'array dall'indice 0 a name.length - 1dove si ottiene il name.lengthnumero di oggetti.

Anche mentre usi un forciclo hai iniziato con l'indice zero e dovresti finire con name.length - 1. In un array a [n] è possibile accedere dal modulo a [0] a un [n-1].

Per esempio:

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

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

Nel tuo caso:

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

for(int i = 0; i<=name.length; i++) {
    System.out.print(name[i] +'\n');
}

5

Per il tuo array dato la lunghezza dell'array è 3 (cioè name.length = 3). Ma poiché memorizza l'elemento a partire dall'indice 0, ha l'indice massimo 2.

Quindi, invece di 'i ** <= name.length' dovresti scrivere 'i <** name.length' per evitare 'ArrayIndexOutOfBoundsException'.


3

Tanto per questa semplice domanda, ma volevo solo evidenziare una nuova funzionalità in Java che eviterà tutte le confusioni sull'indicizzazione negli array anche per i principianti. Java-8 ha sottratto il compito di iterare per te.

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

Qual è il vantaggio? Bene, una cosa è la leggibilità come l'inglese. In secondo luogo, non devi preoccuparti diArrayIndexOutOfBoundsException


3

Stai diventando ArrayIndexOutOfBoundsExceptioncausa di i<=name.lengthparte. name.lengthrestituisce la lunghezza della stringa name, che è 3. Quindi, quando si tenta di accedere name[3], è illegale e genera un'eccezione.

Codice risolto:

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

È definito nelle specifiche del linguaggio Java :

Il public finalcampo length, che contiene il numero di componenti dell'array. lengthpuò essere positivo o zero.


3

Indice della Matrice Fuori Dai Limiti d'Eccezione

Ecco come appare questo tipo di eccezione quando viene lanciato in Eclipse. Il numero in rosso indica l'indice a cui hai tentato di accedere. Quindi il codice sarebbe simile al seguente:

myArray[5]

L'errore viene generato quando si tenta di accedere a un indice che non esiste in quell'array. Se un array ha una lunghezza di 3,

int[] intArray = new int[3];

quindi gli unici indici validi sono:

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

Se un array ha una lunghezza di 1,

int[] intArray = new int[1];

quindi l'unico indice valido è:

intArray[0]

Qualsiasi numero intero uguale alla lunghezza dell'array o maggiore di esso: è fuori limite.

Qualsiasi numero intero inferiore a 0: è fuori limite;

PS: Se cerchi di comprendere meglio gli array e fai alcuni esercizi pratici, ecco un video qui: tutorial sugli array in Java


3

Per le matrici multidimensionali, può essere difficile assicurarsi di accedere alla lengthproprietà della dimensione giusta. Prendi ad esempio il seguente codice:

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

Ogni dimensione ha una lunghezza diversa, quindi il bug sottile è che i loop medio e interno usano la lengthproprietà della stessa dimensione (perché a[i].lengthè la stessa di a[j].length).

Invece, il ciclo interno dovrebbe usare a[i][j].length(o a[0][0].length, per semplicità).


Aggiunto un esempio di codice da Perché il mio ciclo for non funziona quando cambio la condizione (array multidimensionali)? poiché questa domanda viene utilizzata come destinazione duplicata per qualsiasi domanda relativa a ArrayIndexOutOfBoundsException.
Bill the Lizard,

2

Il caso più comune che ho visto per ArrayIndexOutOfBoundsExceptions apparentemente misterioso, cioè apparentemente non causato dal tuo codice di gestione dell'array, è l'uso simultaneo di SimpleDateFormat. In particolare in un servlet o controller:

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

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

Se due thread entrano nel metodo SimplateDateFormat.parse () insieme, probabilmente vedrai un ArrayIndexOutOfBoundsException. Nota la sezione di sincronizzazione della classe javadoc per SimpleDateFormat .

Assicurarsi che non vi sia spazio nel codice che acceda a classi non sicure del thread come SimpleDateFormat in modo simultaneo come in un servlet o controller. Controlla tutte le variabili di istanza dei tuoi servlet e controller per possibili sospetti.


2

ArrayIndexOutOfBoundsException ogni volta che si presenta questa eccezione significa che stai cercando di usare un indice di array che è fuori dai suoi limiti o in termini da uomo che stai richiedendo più di quanto tu abbia inizializzato.

Per evitare ciò, assicurarsi sempre di non richiedere un indice non presente nell'array, ad esempio se la lunghezza dell'array è 10, l'indice deve essere compreso tra 0 e 9


2

ArrayIndexOutOfBounds significa che stai tentando di indicizzare una posizione all'interno di un array che non è allocato.

In questo caso:

String[] name = { "tom", "dick", "harry" };
for (int i = 0; i <= name.length; i++) {
    System.out.println(name[i]);
}
  • name.length è 3 poiché l'array è stato definito con oggetti String 3.
  • Quando si accede al contenuto di un array, la posizione inizia da 0. Dato che ci sono 3 elementi, significherebbe nome [0] = "tom", nome [1] = "dick" e nome [2] = "harry
  • Quando si esegue un ciclo, dal momento che può essere inferiore o uguale a diverrà name.lenght, si sta tentando di nome accesso [3] che non è disponibile.

Per aggirare questo ...

  • Nel tuo ciclo for, puoi fare i <name.length. Ciò impedirebbe il looping al nome [3] e si fermerebbe invece al nome [2]

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

  • Usa a per ogni ciclo

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

  • Usa list.forEach (azione del consumatore) (richiede Java8)

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

  • Converti array in streaming: questa è una buona opzione se si desidera eseguire ulteriori "operazioni" nel proprio array, ad es. Filtro, trasformazione del testo, conversione in una mappa ecc. (Richiede Java8)

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


1

ArrayIndexOutOfBoundsExceptionsignifica che si sta tentando di accedere a un indice dell'array che non esiste o che è fuori limite di questo array. Gli indici di array iniziano da 0 e terminano alla fine - 1 .

Nel tuo caso

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

ArrayIndexOutOfBoundsExceptionaccade quando si sta tentando di accedere all'elemento indicizzato name.length che non esiste (l'indice dell'array termina alla lunghezza -1). la semplice sostituzione di <= con <risolverebbe questo problema.

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

1

Per qualsiasi array di lunghezza n, gli elementi dell'array avranno un indice da 0 a n-1.

Se il tuo programma sta tentando di accedere a qualsiasi elemento (o memoria) con indice di array maggiore di n-1, Java genererà ArrayIndexOutOfBoundsException

Quindi ecco due soluzioni che possiamo usare in un programma

  1. Mantenimento del conteggio:

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

    O qualche altra dichiarazione ciclica come

    int count = 0;
    while(count < array.length) {
        System.out.println(array[count]);
        count++;
    }
  2. Un modo migliore di procedere con a per ogni ciclo, in questo metodo un programmatore non ha bisogno di preoccuparsi del numero di elementi nell'array.

    for(String str : array) {
        System.out.println(str);
    }

1

Secondo il tuo codice:

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

Se si controlla System.out.print (name.length);

otterrai 3;

ciò significa che la lunghezza del tuo nome è 3

il tuo ciclo è in esecuzione da 0 a 3, che dovrebbe essere in esecuzione da "0 a 2" o "1 a 3"

Risposta

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

1

Ogni elemento in un array è chiamato elemento e ogni elemento è accessibile dal suo indice numerico. Come mostrato nella figura precedente, la numerazione inizia con 0 . Il nono elemento, ad esempio, sarebbe quindi accessibile all'indice 8.

IndexOutOfBoundsException viene generato per indicare che un indice di un certo tipo (ad esempio un array, una stringa o un vettore) non è compreso nell'intervallo.

È possibile accedere a qualsiasi array X, da [0 a (X.length - 1)]


1

Vedo qui tutte le risposte che spiegano come lavorare con le matrici e come evitare le eccezioni dell'indice fuori dai limiti. Evito personalmente gli array a tutti i costi. Uso le classi Collections, il che evita tutta la stupidità di dover affrontare interamente gli indici di array. I costrutti di loop funzionano magnificamente con raccolte che supportano codice che è sia più facile da scrivere, capire e mantenere.


1

Se si utilizza la lunghezza di un array per controllare l'iterazione di un ciclo for , ricordare sempre che l'indice del primo elemento in un array è 0 . Quindi l'indice dell'ultimo elemento in un array è uno in meno della lunghezza dell'array.


0

ArrayIndexOutOfBoundsException il nome stesso spiega che se si sta tentando di accedere al valore dell'indice che non rientra nell'ambito delle dimensioni dell'array, si verifica un tale tipo di eccezione.

Nel tuo caso, puoi semplicemente rimuovere il segno di uguale dal tuo ciclo for.

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

L'opzione migliore è iterare un array:

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

0

Questo errore si verifica in caso di cicli eccessivamente lunghi. Consideriamo un esempio semplice come questo,

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]+"  ");
    }
}

Inizialmente, ho inizializzato un array come 'numberArray'. quindi, alcuni elementi dell'array vengono stampati usando per loop. Quando il ciclo esegue il tempo 'i', stampa l'elemento (numberArray [i + 1] .. (quando il valore i è 1, viene stampato l'elemento numberArray [i + 1].) .. Supponi che, quando i = (numberArray. lunghezza-2), viene stampato l'ultimo elemento dell'array ... Quando il valore 'i' va a (numberArray.length-1), nessun valore per la stampa ... In quel punto, si verifica 'ArrayIndexOutOfBoundsException'. Spero che tu possa ottenere idea.grazie!


0

È possibile utilizzare Opzionale in stile funzionale per evitare NullPointerExceptione 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);
}

Produzione:

AAA
NO_DATA
CCC
NO_DATA

-4

Non è possibile iterare o archiviare più dati della lunghezza dell'array. In questo caso potresti fare così:

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

O questo:

for (int i = 0; i < name.length; i++) {
    // ...
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.