Che cosa causa un java.lang.ArrayIndexOutOfBoundsException e come faccio a prevenirlo?
Cosa significa ArrayIndexOutOfBoundsException
e come posso liberarmene?
Ecco un esempio di codice che attiva l'eccezione:
String[] name = {"tom", "dick", "harry"};
for(int i = 0; i<=name.length; i++) {
System.out.print(name[i] +'\n');
}
20 answers
Il tuo primo porto di scalo dovrebbe essere la documentazione che lo spiega ragionevolmente chiaramente:
Generato per indicare che a un array è stato effettuato l'accesso 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... non farlo. Fai attenzione con i tuoi indici di array.
Un problema in cui le persone a volte si imbattono è pensare che gli array siano 1-indicizzato, ad esempio
int[] array = new int[5];
// ... populate the array here ...
for (int index = 1; index <= array.length; index++)
{
System.out.println(array[index]);
}
Che perderà il primo elemento (indice 0) e genererà un'eccezione quando l'indice è 5. Gli indici validi qui sono 0-4 inclusi. L'istruzione for
corretta e idiomatica qui sarebbe:
for (int index = 0; index < array.length; index++)
(Questo presuppone che tuabbia bisogno di l'indice, ovviamente. Se invece è possibile utilizzare il ciclo for avanzato, farlo.)
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];
}
Vedi anche:
Aggiorna: secondo il tuo frammento di codice,
for(int i = 0; i<=name.length; i++) {
L'indice include la lunghezza dell'array. Questo è fuori dai limiti. È necessario sostituire <=
con <
.
for(int i = 0; i < name.length; i++) {
Per dirla in breve:
Nell'ultima iterazione di
for(int i = 0; i<=name.length; i++) {
i
sarà uguale a name.length
che è un indice illegale, poiché gli indici di array sono basati su zero.
Il tuo codice dovrebbe leggere
for(int i = 0; i < name.length; i++)
^
Significa che si sta tentando di accedere a un indice di un array che non è valido in quanto non è tra i limiti.
Ad esempio questo inizializzerebbe un array intero primitivo con il limite superiore 4.
int intArray[] = new int[5];
I programmatori contano da zero. Quindi questo ad esempio genererebbe un ArrayIndexOutOfBoundsException
poiché il limite superiore è 4 e non 5.
intArray[5];
Per evitare un'eccezione out-of-bounds dell'indice di matrice, si dovrebbe usare enhanced-for
dichiarazione dove e quando possono.
La motivazione principale (e il caso d'uso) è quando si esegue l'iterazione e non si richiedono passaggi di iterazione complicati. Si dovrebbe non essere in grado di utilizzare un enhanced-for
per spostarsi all'indietro in un array o solo iterare su ogni altro elemento.
Hai la garanzia di non esaurire gli elementi da iterare quando lo fai, e il tuo [corretto] esempio è facilmente convertito sopra.
Il seguente codice:
String[] name = {"tom", "dick", "harry"};
for(int i = 0; i< name.length; i++) {
System.out.print(name[i] + "\n");
}
Equivalent è equivalente a questo:
String[] name = {"tom", "dick", "harry"};
for(String firstName : name) {
System.out.println(firstName + "\n");
}
Quali sono le cause ArrayIndexOutOfBoundsException
?
Se si pensa a una variabile come a una "casella" in cui è possibile inserire un valore, allora un array è una serie di caselle poste l'una accanto all'altra, dove il numero di caselle è un numero intero finito ed esplicito.
Creazione di un array come questo:
final int[] myArray = new int[5]
Crea una fila di 5 caselle, ciascuna contenente un int
. Ciascuna delle caselle ha un indice, una posizione nella serie di caselle. Questo indice inizia da 0 e termina a N-1, dove N è la dimensione dell'array (il numero di caselle).
Per recuperare uno dei valori da questa serie di caselle, è possibile fare riferimento ad esso attraverso il suo indice, in questo modo:
myArray[3]
Che ti darà il valore della 4a casella della serie (poiché la prima casella ha indice 0).
Un ArrayIndexOutOfBoundsException
è causato dal tentativo di ripristinare una "casella" che non esiste, passando un indice superiore all'indice dell'ultima "casella" o negativo.
Con il mio esempio in esecuzione, questi frammenti di codice produrrebbero un 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
Al fine di prevenire ArrayIndexOutOfBoundsException
, ci sono alcuni punti chiave da considerare:
Ciclo
Quando si esegue il loop di un array, assicurarsi sempre che l'indice che si sta recuperando sia strettamente inferiore alla lunghezza dell'array (il numero di caselle). Ad esempio:
for (int i = 0; i < myArray.length; i++) {
Nota il <
, non mescolare mai un =
lì dentro..
Si potrebbe desiderare di essere tentati di fare qualcosa di simile questo:
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 un sacco di dolore.
Ove possibile, usare foreach:
for (int value : myArray) {
In questo modo non dovrai pensare affatto agli indici.
Durante il ciclo, qualunque cosa tu faccia, NON cambiare MAI il valore dell'iteratore del ciclo (qui: i
). L'unico posto in cui questo dovrebbe cambiare valore è quello di mantenere il ciclo in corso. Cambiarlo altrimenti rischia solo un'eccezione, e nella maggior parte dei casi no necessario.
Recupero / 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];
}
Nel codice è stato effettuato l'accesso agli elementi dall'indice 0 alla lunghezza dell'array di stringhe. name.length
fornisce il numero di oggetti string nel tuo array di oggetti string cioè 3, ma puoi accedere solo fino all'indice 2 name[2]
,
perché è possibile accedere all'array dall'indice 0 a name.length - 1
dove si ottiene name.length
numero di oggetti.
Anche durante l'utilizzo di un ciclo for
hai iniziato con index zero e dovresti terminare con name.length - 1
. In un array a [n] è possibile accedere al modulo a[0] a a[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');
}
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 astratto 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 è necessario preoccuparsi del ArrayIndexOutOfBoundsException
ArrayIndexOutOfBoundsException
significa che si sta tentando di accedere a un indice della matrice che non esiste o fuori dal limite di questa matrice. Gli indici degli array iniziano da 0 e termina a lunghezza-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
}
ArrayIndexOutOfBoundsException
accade quando si sta tentando di accedere
nome.elemento indicizzato di lunghezza che non esiste (l'indice dell'array termina alla lunghezza -1). la semplice sostituzione di
for(int i = 0; i < name.length; i++) {
System.out.print(name[i] +'\n'); // i goes from 0 to length - 1, Correct
}
Il caso più comune che ho visto per ArrayIndexOutOfBoundsExceptions apparentemente misterioso, cioè apparentemente non causato dal proprio 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 in SimplateDateFormat.metodo parse () insieme probabilmente vedrai un ArrayIndexOutOfBoundsException. Si noti la sezione di sincronizzazione della classe javadoc per SimpleDateFormat .
Assicurarsi che ci sia nessun posto nel codice che accede a classi thread non sicure come SimpleDateFormat in modo simultaneo come in un servlet o controller. Controlla tutte le variabili di istanza dei tuoi servlet e controller per probabili sospetti.
Stai ricevendo ArrayIndexOutOfBoundsException
a causa della parte i<=name.length
. name.length
restituisce la lunghezza della stringa name
, che è 3. Quindi quando si tenta di accedere a 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 nella specifica del linguaggio Java :
Il campo
public final
length
, che contiene il numero di componenti della matrice.length
può essere positivo o zero.
Ecco come appare questo tipo di eccezione quando viene lanciato in Eclipse. Il numero in rosso indica l'indice a cui si è tentato di accedere. Quindi il codice sarebbe simile a questo:
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 una matrice ha una lunghezza di 1,
int[] intArray = new int[1];
Quindi l'unico indice valido è:
intArray[0]
Qualsiasi intero uguale alla lunghezza dell'array, o più grande di esso: è fuori dai limiti.
Qualsiasi numero intero inferiore a 0: è fuori dai limiti;
POST scriptum: Se si cerca di avere una migliore comprensione degli array e fare alcuni esercizi pratici, c'è un video qui: tutorial sugli array in Java
Per l'array dato la lunghezza dell'array è 3 (cioè nome.lunghezza = 3). Ma poiché memorizza l'elemento a partire dall'indice 0, ha un indice massimo 2.
Quindi, invece di 'i** nome.lunghezza 'dovresti scrivere' i
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
-
Mantenimento del conteggio:
for(int count = 0; count < array.length; count++) { System.out.println(array[count]); }
O qualche altra istruzione di loop come
int count = 0; while(count < array.length) { System.out.println(array[count]); count++; }
-
Un modo migliore vai con a per ciascuno loop, in questo metodo un programmatore non ha bisogno di preoccuparsi del numero di elementi nell'array.
for(String str : array) { System.out.println(str); }
ArrayIndexOutOfBoundsException
il nome stesso spiega che se si tenta di accedere al valore all'indice che è fuori dall'ambito della dimensione dell'array, si verifica questo 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 è quella di iterare un array:
for(String i : name )
System.out.println(i);
Per gli array multidimensionali, può essere difficile assicurarsi di accedere alla proprietà length
della giusta dimensione. 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 centrale e interno usano la proprietà length
della stessa dimensione (perché a[i].length
è uguale a a[j].length
).
Invece, il ciclo interno dovrebbe usare a[i][j].length
(o a[0][0].length
, per semplicità).
Questo errore si verifica nei tempi di overlimit del ciclo di esecuzione.Consideriamo un semplice esempio 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]+" ");
}
}
All'inizio, ho inizializzato un array come 'numberArray'. quindi, alcuni elementi dell'array vengono stampati usando for loop. Quando loop esegue il tempo 'i', stampa l'elemento (numberArray[i+1]..(quando il valore i è 1, viene stampato l'elemento numberArray[i+1].)..Supponiamo che, quando i=(numberArray.length-2), viene stampato l'ultimo elemento dell'array..Quando il valore ' i ' va a (numberArray.lunghezza-1), nessun valore per printing..In quel punto,' ArrayIndexOutOfBoundsException ' si verifica.Spero che tu possa avere un'idea.Grazie!
ArrayIndexOutOfBoundsException ogni volta che arriva questa eccezione significa che stai cercando di utilizzare un indice di array che è fuori dai suoi limiti o in termini laici stai richiedendo più di quanto hai inizializzato.
Per evitare ciò assicurati sempre di non richiedere un indice che non è presente nell'array, ovvero se la lunghezza dell'array è 10, l'indice deve variare da 0 a 9
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 Sistema.fuori.stampa (nome.lunghezza);
Otterrai 3;
Significa che la lunghezza del tuo nome è 3
Il tuo ciclo è in esecuzione da 0 a 3 che dovrebbe essere in esecuzione "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');
}
Non è possibile iterare o memorizzare 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++) {
// ...
}