Was verursacht eine java.lang.ArrayIndexOutOfBoundsException und wie verhindere ich sie?

298

Was ArrayIndexOutOfBoundsExceptionbedeutet und wie werde ich es los?

Hier ist ein Codebeispiel, das die Ausnahme auslöst:

String[] names = { "tom", "bob", "harry" };
for (int i = 0; i <= names.length; i++) {
    System.out.println(names[i]);
}
Aaron
quelle
1
In Bezug auf die letzte Frage wäre Code hilfreich. Greifen Sie mit einem bekannten Index auf das Array zu oder müssen Sie mit dem Debuggen beginnen, um herauszufinden, wie der Index berechnet wird, wenn der Fehler auftritt?
Justkt
43
Ersetzen Sie i <= name.lengthdurch i < name.length- oder schreiben Sie eine erweiterte for-Schleife. ( for (String aName : name) { ... })
Jean Hominal
1
Dies bedeutet, dass Sie ein Element eines Arrays erhalten möchten, das nicht vorhanden ist. 'i <= name.length' bedeutet, dass Sie eine Elementlänge von + 1 erhalten möchten - es ist nicht vorhanden.
Gbk

Antworten:

296

Ihre erste Anlaufstelle sollte die Dokumentation sein, die dies einigermaßen klar erklärt:

Wird ausgelöst, um anzuzeigen, dass auf ein Array mit einem unzulässigen Index zugegriffen wurde. Der Index ist entweder negativ oder größer oder gleich der Größe des Arrays.

Also zum Beispiel:

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

Wie man es vermeidet ... ähm, tu das nicht. Seien Sie vorsichtig mit Ihren Array-Indizes.

Ein Problem, auf das Menschen manchmal stoßen, ist der Gedanke, dass Arrays 1-indiziert sind, z

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

Dadurch wird das erste Element (Index 0) übersehen und eine Ausnahme ausgelöst, wenn der Index 5 ist. Die gültigen Indizes hier sind 0-4 einschließlich. Die richtige, idiomatische forAussage hier wäre:

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

( Dies setzt natürlich voraus, dass Sie den Index benötigen . Wenn Sie stattdessen die erweiterte for-Schleife verwenden können, tun Sie dies.)

Jon Skeet
quelle
1
Ich würde hinzufügen, dass für mehrdimensionale Arrays, die in Java eine beliebige Form haben könnten, die verschachtelten Schleifen auf die relevante Länge des Subarrays prüfen sollten : 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];
}

Siehe auch:


Update : gemäß Ihrem Code-Snippet,

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

Der Index enthält die Länge des Arrays. Dies ist außerhalb der Grenzen. Sie müssen ersetzen <=durch <.

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

Aus diesem ausgezeichneten Artikel: ArrayIndexOutOfBoundsException in for-Schleife

Um es kurz auszudruecken:

In der letzten Iteration von

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

iwird gleich, name.lengthwas ein unzulässiger Index ist, da Array-Indizes auf Null basieren.

Ihr Code sollte lauten

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

Dies bedeutet, dass Sie versuchen, auf einen Index eines Arrays zuzugreifen, der nicht gültig ist, da er nicht zwischen den Grenzen liegt.

Dies würde beispielsweise ein primitives ganzzahliges Array mit der Obergrenze 4 initialisieren.

int intArray[] = new int[5];

Programmierer zählen von Null. So würde dies zum Beispiel ein werfen, ArrayIndexOutOfBoundsExceptionda die Obergrenze 4 und nicht 5 ist.

intArray[5];
Octavian A. Damiean
quelle
4
Grenzen sind die Grenzen innerhalb des Bereichs. dh; 0-5
John Giotta
11

Um eine Ausnahme außerhalb der Grenzen des Array-Index zu vermeiden, sollte die erweitertefor Anweisung verwendet werden, wo und wann dies möglich ist.

Die Hauptmotivation (und der Anwendungsfall) besteht darin, dass Sie iterieren und keine komplizierten Iterationsschritte benötigen. Sie können ein erweitertes Element nicht verwenden for, um sich in einem Array rückwärts zu bewegen oder nur jedes andere Element zu iterieren.

Dabei gehen Ihnen garantiert nicht die Elemente aus, über die Sie iterieren können, und Ihr [korrigiertes] Beispiel kann problemlos konvertiert werden.

Der folgende Code:

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

... ist gleichbedeutend damit:

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

Was verursacht ArrayIndexOutOfBoundsException?

Wenn Sie sich eine Variable als "Box" vorstellen, in der Sie einen Wert platzieren können, ist ein Array eine Reihe von Boxen nebeneinander, wobei die Anzahl der Boxen eine endliche und explizite Ganzzahl ist.

Erstellen eines Arrays wie folgt:

final int[] myArray = new int[5]

erstellt eine Reihe von 5 Feldern mit jeweils einem int. Jedes der Felder hat einen Index, eine Position in der Reihe der Felder. Dieser Index beginnt bei 0 und endet bei N-1, wobei N die Größe des Arrays (die Anzahl der Felder) ist.

Um einen der Werte aus dieser Reihe von Feldern abzurufen, können Sie über seinen Index wie folgt darauf verweisen:

myArray[3]

Damit erhalten Sie den Wert der 4. Box in der Reihe (da die erste Box den Index 0 hat).

Ein ArrayIndexOutOfBoundsExceptionwird dadurch verursacht, dass versucht wird, eine nicht vorhandene "Box" abzurufen, indem ein Index übergeben wird, der höher als der Index der letzten "Box" oder negativ ist.

In meinem laufenden Beispiel würden diese Codefragmente eine solche Ausnahme erzeugen:

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

Wie vermeide ich? ArrayIndexOutOfBoundsException

Um dies zu verhindern ArrayIndexOutOfBoundsException, sind einige wichtige Punkte zu beachten:

Looping

Stellen Sie beim Durchlaufen eines Arrays immer sicher, dass der Index, den Sie abrufen, streng kleiner ist als die Länge des Arrays (die Anzahl der Felder). Zum Beispiel:

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

Beachten Sie die <, mischen Sie nie ein =in dort ..

Vielleicht möchten Sie versucht sein, so etwas zu tun:

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

Tu es einfach nicht. Halten Sie sich an die obige (wenn Sie den Index verwenden müssen) und es erspart Ihnen viel Schmerz.

Verwenden Sie nach Möglichkeit foreach:

for (int value : myArray) {

Auf diese Weise müssen Sie überhaupt nicht an Indizes denken.

Ändern Sie beim Schleifen NIEMALS den Wert des Schleifeniterators (hier :) i. Der einzige Ort, an dem sich der Wert ändern sollte, ist, die Schleife am Laufen zu halten. Eine andere Änderung birgt nur das Risiko einer Ausnahme und ist in den meisten Fällen nicht erforderlich.

Abrufen / Aktualisieren

Überprüfen Sie beim Abrufen eines beliebigen Elements des Arrays immer, ob es sich um einen gültigen Index für die Länge des Arrays handelt:

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];
}
Tobb
quelle
6

In Ihrem Code haben Sie auf die Elemente vom Index 0 bis zur Länge des String-Arrays zugegriffen. name.lengthGibt die Anzahl der Zeichenfolgenobjekte in Ihrem Array von Zeichenfolgenobjekten an, dh 3, Sie können jedoch nur auf Index 2 zugreifen name[2], da auf das Array von Index 0 bis zu der Stelle zugegriffen werden kann, name.length - 1an der Sie die name.lengthAnzahl der Objekte erhalten.

Selbst wenn Sie eine forSchleife verwenden, haben Sie mit dem Index Null begonnen und sollten mit enden name.length - 1. In einem Array a [n] können Sie von a [0] auf a [n-1] zugreifen.

Zum Beispiel:

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

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

In deinem Fall:

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

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

Für Ihr angegebenes Array beträgt die Länge des Arrays 3 (dh name.length = 3). Da es jedoch Elemente ab Index 0 speichert, hat es den maximalen Index 2.

Anstelle von 'i ** <= name.length' sollten Sie also 'i <** name.length' schreiben, um ' ArrayIndexOutOfBoundsException' zu vermeiden.

Nikhil
quelle
3

Soviel zu dieser einfachen Frage, aber ich wollte nur eine neue Funktion in Java hervorheben, die selbst für Anfänger alle Verwirrungen bei der Indizierung in Arrays vermeidet. Java-8 hat die Aufgabe des Iterierens für Sie abstrahiert.

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

Was ist der Vorteil? Nun, eine Sache ist die Lesbarkeit wie Englisch. Zweitens brauchen Sie sich keine Sorgen zu machenArrayIndexOutOfBoundsException

Satyendra Kumar
quelle
3

Sie bekommen ArrayIndexOutOfBoundsExceptionwegen i<=name.lengthTeil. name.lengthGeben Sie die Länge der Zeichenfolge zurück name, die 3 ist. Wenn Sie also versuchen, darauf zuzugreifen name[3], ist dies unzulässig und löst eine Ausnahme aus.

Aufgelöster Code:

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

Es ist in der Java-Sprachspezifikation definiert :

Das public finalFeld length, das die Anzahl der Komponenten des Arrays enthält. lengthkann positiv oder null sein.

Roottraveller
quelle
3

Array-Index außerhalb der Grenzen Ausnahme

So sieht diese Art von Ausnahme aus, wenn sie in Eclipse ausgelöst wird. Die rote Zahl kennzeichnet den Index, auf den Sie zugreifen wollten. Der Code würde also so aussehen:

myArray[5]

Der Fehler wird ausgelöst, wenn Sie versuchen, auf einen Index zuzugreifen, der in diesem Array nicht vorhanden ist. Wenn ein Array eine Länge von 3 hat,

int[] intArray = new int[3];

dann sind die einzigen gültigen Indizes:

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

Wenn ein Array eine Länge von 1 hat,

int[] intArray = new int[1];

dann ist der einzig gültige Index:

intArray[0]

Jede Ganzzahl, die der Länge des Arrays entspricht oder größer als diese ist, ist außerhalb der Grenzen.

Jede Ganzzahl kleiner als 0: ist außerhalb der Grenzen;

PS: Wenn Sie Arrays besser verstehen und einige praktische Übungen machen möchten, finden Sie hier ein Video: Tutorial zu Arrays in Java

Johny
quelle
3

Bei mehrdimensionalen Arrays kann es schwierig sein, sicherzustellen, dass Sie auf die lengthEigenschaft der richtigen Dimension zugreifen . Nehmen Sie zum Beispiel den folgenden Code:

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

Jede Dimension hat eine andere Länge, daher besteht der subtile Fehler darin, dass die mittlere und die innere Schleife die lengthEigenschaft derselben Dimension verwenden (weil a[i].lengthdieselbe wie a[j].length).

Stattdessen sollte die innere Schleife verwendet werden a[i][j].length(oder der a[0][0].lengthEinfachheit halber).

Bill die Eidechse
quelle
Es wurde ein Codebeispiel von Warum funktioniert meine for-Schleife nicht, wenn ich die Bedingung ändere (mehrdimensionale Arrays) hinzugefügt ? da diese Frage als Dupe-Ziel für jede Frage verwendet wird, die sich mit ArrayIndexOutOfBoundsException befasst.
Bill the Lizard
2

Der häufigste Fall, den ich für scheinbar mysteriöse ArrayIndexOutOfBoundsExceptions gesehen habe, dh anscheinend nicht durch Ihren eigenen Code für die Array-Behandlung verursacht wurde, ist die gleichzeitige Verwendung von SimpleDateFormat. Insbesondere in einem Servlet oder 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"));
  }
}

Wenn zwei Threads zusammen die SimplateDateFormat.parse () -Methode eingeben, wird wahrscheinlich eine ArrayIndexOutOfBoundsException angezeigt. Beachten Sie den Synchronisationsabschnitt der Klasse javadoc für SimpleDateFormat .

Stellen Sie sicher, dass in Ihrem Code kein Platz vorhanden ist, der gleichzeitig auf unsichere Thread-Klassen wie SimpleDateFormat zugreift, wie in einem Servlet oder Controller. Überprüfen Sie alle Instanzvariablen Ihrer Servlets und Controller auf mögliche Verdächtige.

Kyri Sarantakos
quelle
2

ArrayIndexOutOfBoundsException Wenn diese Ausnahme auftritt, bedeutet dies, dass Sie versuchen, einen Index des Arrays zu verwenden, der außerhalb seiner Grenzen liegt, oder in Laienbegriffen mehr anfordern, als Sie initialisiert haben.

Um dies zu verhindern, stellen Sie immer sicher, dass Sie keinen Index anfordern, der nicht im Array vorhanden ist. Wenn die Array-Länge 10 beträgt, muss Ihr Index zwischen 0 und 9 liegen

sgrpwr
quelle
2

ArrayIndexOutOfBounds bedeutet, dass Sie versuchen, eine Position innerhalb eines nicht zugewiesenen Arrays zu indizieren.

In diesem Fall:

String[] name = { "tom", "dick", "harry" };
for (int i = 0; i <= name.length; i++) {
    System.out.println(name[i]);
}
  • name.length ist 3, da das Array mit 3 String-Objekten definiert wurde.
  • Beim Zugriff auf den Inhalt eines Arrays beginnt die Position bei 0. Da es 3 Elemente gibt, bedeutet dies name [0] = "tom", name [1] = "dick" und name [2] = "harry"
  • Wenn Sie eine Schleife ausführen, versuchen Sie, auf den nicht verfügbaren Namen [3] zuzugreifen , da i kleiner oder gleich name.length sein kann.

Um dies zu umgehen ...

  • In Ihrer for-Schleife können Sie i <name.length ausführen. Dies würde eine Schleife zum Namen [3] verhindern und stattdessen bei Name [2] anhalten.

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

  • Verwenden Sie für jede Schleife ein

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

  • Verwenden Sie list.forEach (Consumer-Aktion) (erfordert Java8)

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

  • Array in Stream konvertieren - Dies ist eine gute Option, wenn Sie zusätzliche 'Operationen' für Ihr Array ausführen möchten, z. B. filtern, den Text transformieren, in eine Karte konvertieren usw. (erfordert Java8).

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

martinywwan
quelle
1

ArrayIndexOutOfBoundsExceptionbedeutet, dass Sie versuchen, auf einen Index des Arrays zuzugreifen, der nicht vorhanden ist oder außerhalb der Grenzen dieses Arrays liegt. Array-Indizes beginnen bei 0 und enden bei der Länge - 1 .

In deinem Fall

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

ArrayIndexOutOfBoundsExceptiontritt auf, wenn Sie versuchen, auf das nicht vorhandene indizierte Element name.length zuzugreifen (Array-Index endet mit der Länge -1). Nur <= durch <zu ersetzen, würde dieses Problem lösen.

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

Für jedes Array der Länge n haben Elemente des Arrays einen Index von 0 bis n-1.

Wenn Ihr Programm versucht, auf ein Element (oder einen Speicher) mit einem Array-Index größer als n-1 zuzugreifen , löst Java eine ArrayIndexOutOfBoundsException aus

Hier sind zwei Lösungen, die wir in einem Programm verwenden können

  1. Anzahl beibehalten:

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

    Oder eine andere Schleifenanweisung wie

    int count = 0;
    while(count < array.length) {
        System.out.println(array[count]);
        count++;
    }
  2. Ein besserer Weg mit a für jede Schleife, bei dieser Methode muss sich ein Programmierer nicht um die Anzahl der Elemente im Array kümmern.

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

Gemäß Ihrem Code:

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

Wenn Sie System.out.print (name.length) überprüfen;

du wirst 3 bekommen;

Das bedeutet, dass Ihre Namenslänge 3 beträgt

Ihre Schleife läuft von 0 bis 3, wobei entweder "0 bis 2" oder "1 bis 3" ausgeführt werden sollte.

Antworten

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

Jedes Element in einem Array wird als Element bezeichnet, und auf jedes Element wird über seinen numerischen Index zugegriffen. Wie in der vorhergehenden Abbildung gezeigt, beginnt die Nummerierung mit 0 . Auf das 9. Element würde daher beispielsweise bei Index 8 zugegriffen.

IndexOutOfBoundsException wird ausgelöst, um anzuzeigen, dass ein Index (z. B. für ein Array, eine Zeichenfolge oder einen Vektor) außerhalb des Bereichs liegt.

Auf jedes Array X kann von [0 bis (X. Länge - 1)] zugegriffen werden.

ZiadM
quelle
1

Ich sehe hier alle Antworten, die erklären, wie man mit Arrays arbeitet und wie man den Index außerhalb der Grenzen vermeidet. Ich persönlich vermeide Arrays um jeden Preis. Ich verwende die Collections-Klassen, wodurch die Dummheit vermieden wird, sich vollständig mit Array-Indizes befassen zu müssen. Die Schleifenkonstrukte funktionieren hervorragend mit Sammlungen, die Code unterstützen, der sowohl einfacher zu schreiben, zu verstehen als auch zu warten ist.

John Czukkermann
quelle
1

Wenn Sie die Länge eines Arrays verwenden, um die Iteration einer for- Schleife zu steuern , denken Sie immer daran, dass der Index des ersten Elements in einem Array 0 ist . Der Index des letzten Elements in einem Array ist also eins weniger als die Länge des Arrays.

Sachithra Dilshan
quelle
0

ArrayIndexOutOfBoundsException Der Name selbst erklärt, dass eine solche Ausnahme auftritt, wenn Sie versuchen, auf den Wert am Index zuzugreifen, der außerhalb des Bereichs der Array-Größe liegt.

In Ihrem Fall können Sie einfach das Gleichheitszeichen aus Ihrer for-Schleife entfernen.

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

Die bessere Option besteht darin, ein Array zu iterieren:

for(String i : name )
      System.out.println(i);
Madhusudan Sharma
quelle
0

Dieser Fehler tritt bei Laufbegrenzungsüberschreitungszeiten auf. Betrachten wir ein einfaches Beispiel wie dieses:

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

Zuerst habe ich ein Array als 'numberArray' initialisiert. Anschließend werden einige Array-Elemente mit der for-Schleife gedruckt. Wenn die Schleife die Zeit 'i' ausführt, drucken Sie das Element (numberArray [i + 1]. (Wenn der i-Wert 1 ist, wird das Element numberArray [i + 1] gedruckt.). Angenommen, wenn i = (numberArray). Länge-2), das letzte Element des Arrays wird gedruckt. Wenn der Wert 'i' auf (numberArray.length-1) geht, wird kein Wert zum Drucken ausgegeben. In diesem Punkt tritt 'ArrayIndexOutOfBoundsException' auf. Ich hoffe, Sie könnten es bekommen Idee. Danke!

GT_hash
quelle
0

Sie können optionale Verwendung in funktionalem Stil zu vermeiden , NullPointerExceptionund 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);
}

Ausgabe:

AAA
NO_DATA
CCC
NO_DATA
Andrey Lavrukhin
quelle
-4

Sie konnten nicht mehr Daten als die Länge Ihres Arrays iterieren oder speichern. In diesem Fall könnten Sie Folgendes tun:

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

Oder dieses:

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