Qu'est-ce qui cause une exception java.lang.ArrayIndexOutOfBoundsException et comment puis-je l'empêcher?

298

Que ArrayIndexOutOfBoundsExceptionsignifie et comment m'en débarrasser?

Voici un exemple de code qui déclenche l'exception:

String[] names = { "tom", "bob", "harry" };
for (int i = 0; i <= names.length; i++) {
    System.out.println(names[i]);
}
Aaron
la source
1
En référence à la dernière question, le code serait utile. Accédez-vous au tableau avec un index connu, ou devez-vous commencer le débogage pour comprendre comment l'index est calculé lorsque l'erreur se produit?
justkt
43
Remplacez i <= name.lengthpar i < name.length- ou mieux, écrivez une boucle for améliorée. ( for (String aName : name) { ... })
Jean Hominal
1
cela signifie que vous voulez obtenir un élément du tableau qui n'existe pas, 'i <= nom.longueur' signifie que vous voulez obtenir la longueur de l'élément + 1 - ce n'est pas le cas.
gbk

Réponses:

297

Votre premier port d'escale devrait être la documentation qui l'explique assez clairement:

Lancé pour indiquer qu'un tableau a été accédé avec un index illégal. L'index est soit négatif, soit supérieur ou égal à la taille du tableau.

Ainsi, par exemple:

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

Quant à savoir comment l'éviter ... euh, ne fais pas ça. Soyez prudent avec vos index de tableau.

Un problème que les gens rencontrent parfois est de penser que les tableaux sont indexés 1, par exemple

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

Cela manquera le premier élément (index 0) et lèvera une exception lorsque l'index est 5. Les index valides ici sont 0-4 inclus. La fordéclaration idiomatique correcte ici serait:

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

(Cela suppose que vous ayez besoin de l'index, bien sûr. Si vous pouvez utiliser la boucle for améliorée à la place, faites-le.)

Jon Skeet
la source
1
Je rajouterais que pour les tableaux multidimensionnels qui pourraient avoir une forme arbitraire en Java, les boucles imbriquées doivent vérifier la longueur de sous - groupement concerné: 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];
}

Voir également:


Mise à jour : selon votre extrait de code,

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

L'index inclut la longueur du tableau. C'est hors limites. Vous devez remplacer <=par <.

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

De cet excellent article: ArrayIndexOutOfBoundsException dans la boucle for

Pour le dire brièvement:

Dans la dernière itération de

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

isera égal à name.lengthce qui est un index illégal, car les indices de tableau sont à base zéro.

Votre code devrait lire

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

Cela signifie que vous essayez d'accéder à un index d'un tableau qui n'est pas valide car il n'est pas entre les limites.

Par exemple, cela initialiserait un tableau entier primitif avec la borne supérieure 4.

int intArray[] = new int[5];

Les programmeurs comptent à partir de zéro. Ainsi, par exemple, cela lancerait un ArrayIndexOutOfBoundsExceptioncar la limite supérieure est 4 et non 5.

intArray[5];
Octavian A. Damiean
la source
4
Les limites sont les limites à l'intérieur de la plage. c'est à dire; 0-5
John Giotta
11

Pour éviter une exception hors limites d'index de tableau, il faut utiliser l' instruction Enhancedfor où et quand ils le peuvent.

La motivation principale (et le cas d'utilisation) est lorsque vous itérez et que vous n'avez besoin d'aucune étape d'itération compliquée. Vous ne seriez pas en mesure d'utiliser un système amélioré forpour vous déplacer vers l'arrière dans un tableau ou seulement itérer sur tous les autres éléments.

Vous êtes assuré de ne pas manquer d'éléments à répéter lors de cette opération, et votre exemple [corrigé] est facilement converti.

Le code ci-dessous:

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

... équivaut à ceci:

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

Quelles causes ArrayIndexOutOfBoundsException?

Si vous considérez une variable comme une "boîte" où vous pouvez placer une valeur, alors un tableau est une série de boîtes placées côte à côte, où le nombre de boîtes est un entier fini et explicite.

Créer un tableau comme celui-ci:

final int[] myArray = new int[5]

crée une rangée de 5 cases contenant chacune un int. Chacune des cases a un index, une position dans la série des cases. Cet index commence à 0 et se termine à N-1, où N est la taille du tableau (le nombre de cases).

Pour récupérer l'une des valeurs de cette série de cases, vous pouvez vous y référer via son index, comme ceci:

myArray[3]

Ce qui vous donnera la valeur de la 4ème case de la série (puisque la première case a l'index 0).

Un ArrayIndexOutOfBoundsExceptionest provoqué en essayant de récupérer une "boîte" qui n'existe pas, en passant un index supérieur à l'indice de la dernière "boîte", ou négatif.

Avec mon exemple en cours d'exécution, ces extraits de code produiraient une telle exception:

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

Comment éviter ArrayIndexOutOfBoundsException

Afin de prévenir ArrayIndexOutOfBoundsException, il y a quelques points clés à considérer:

Boucle

Lorsque vous parcourez un tableau, assurez-vous toujours que l'index que vous récupérez est strictement inférieur à la longueur du tableau (le nombre de cases). Par exemple:

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

Remarquez le <, ne mélangez jamais un =dedans ..

Vous voudrez peut-être être tenté de faire quelque chose comme ceci:

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

Mais ne le fais pas. Tenez-vous à celui ci-dessus (si vous devez utiliser l'index) et cela vous évitera beaucoup de douleur.

Dans la mesure du possible, utilisez foreach:

for (int value : myArray) {

De cette façon, vous n'aurez pas du tout à penser aux index.

Lors d'une boucle, quoi que vous fassiez, ne modifiez JAMAIS la valeur de l'itérateur de boucle (ici:) i. Le seul endroit où cela devrait changer de valeur est de maintenir la boucle. Le changer autrement ne fait que risquer une exception et n'est pas nécessaire dans la plupart des cas.

Récupération / mise à jour

Lors de la récupération d'un élément arbitraire du tableau, vérifiez toujours qu'il s'agit d'un index valide par rapport à la longueur du tableau:

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
la source
6

Dans votre code, vous avez accédé aux éléments de l'index 0 à la longueur du tableau de chaînes. name.lengthdonne le nombre d'objets chaîne dans votre tableau d'objets chaîne, c'est-à-dire 3, mais vous ne pouvez accéder qu'à l'index 2 name[2], car le tableau est accessible depuis l'index 0 jusqu'à l' name.length - 1endroit où vous obtenez le name.lengthnombre d'objets.

Même en utilisant une forboucle, vous avez commencé avec l'index zéro et vous devriez terminer avec name.length - 1. Dans un tableau a [n], vous pouvez accéder du formulaire a [0] à un [n-1].

Par exemple:

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

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

Dans ton cas:

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

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

Pour votre tableau donné, la longueur du tableau est de 3 (c'est-à-dire name.length = 3). Mais comme il stocke l'élément à partir de l'index 0, il a l'index max 2.

Ainsi, au lieu de «i ** <= name.length», vous devez écrire «i <** name.length» pour éviter «ArrayIndexOutOfBoundsException».

nIKHIL
la source
3

Voilà pour cette question simple, mais je voulais juste mettre en évidence une nouvelle fonctionnalité en Java qui évitera toutes les confusions autour de l'indexation dans les tableaux, même pour les débutants. Java-8 a résumé la tâche d'itérer pour vous.

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

Quel est l'avantage? Eh bien, une chose est la lisibilité comme l'anglais. Deuxièmement, vous n'avez pas à vous soucier de laArrayIndexOutOfBoundsException

Satyendra Kumar
la source
3

Vous obtenez en ArrayIndexOutOfBoundsExceptionraison d'une i<=name.lengthpartie. name.lengthrenvoie la longueur de la chaîne name, qui est 3. Par conséquent, lorsque vous essayez d'accéder name[3], c'est illégal et lève une exception.

Code résolu:

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

Il est défini dans la spécification du langage Java :

Le public finalchamp length, qui contient le nombre de composants du tableau. lengthpeut être positif ou nul.

roottraveller
la source
3

Index de tableau hors limite

Voilà à quoi ressemble ce type d'exception lorsqu'il est lancé dans Eclipse. Le nombre en rouge signifie l'index auquel vous avez essayé d'accéder. Ainsi, le code ressemblerait à ceci:

myArray[5]

L'erreur est levée lorsque vous essayez d'accéder à un index qui n'existe pas dans ce tableau. Si un tableau a une longueur de 3,

int[] intArray = new int[3];

alors les seuls index valides sont:

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

Si un tableau a une longueur de 1,

int[] intArray = new int[1];

alors le seul index valide est:

intArray[0]

Tout entier égal à la longueur du tableau, ou supérieur à celui-ci: est hors limites.

Tout entier inférieur à 0: est hors limites;

PS: Si vous cherchez à mieux comprendre les tableaux et à faire des exercices pratiques, il y a une vidéo ici: tutoriel sur les tableaux en Java

Johny
la source
3

Pour les tableaux multidimensionnels, il peut être difficile de s'assurer que vous accédez à la lengthpropriété de la bonne dimension. Prenons l'exemple du code suivant:

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

Chaque dimension a une longueur différente, donc le bug subtil est que les boucles centrale et intérieure utilisent la lengthpropriété de la même dimension (car a[i].lengthest la même que a[j].length).

Au lieu de cela, la boucle intérieure doit utiliser a[i][j].length(ou a[0][0].length, pour plus de simplicité).

Bill le lézard
la source
Ajout d'un exemple de code de Pourquoi ma boucle for ne fonctionne-t-elle pas lorsque je change la condition (tableaux multidimensionnels)? puisque cette question est utilisée comme cible dupe pour toute question traitant de ArrayIndexOutOfBoundsException.
Bill the Lizard
2

Le cas le plus courant que j'ai vu pour les ArrayIndexOutOfBoundsExceptions apparemment mystérieux, c'est-à-dire apparemment non causés par votre propre code de gestion de tableau, est l'utilisation simultanée de SimpleDateFormat. En particulier dans une servlet ou un contrôleur:

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

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

Si deux threads entrent ensemble la méthode SimplateDateFormat.parse (), vous verrez probablement une exception ArrayIndexOutOfBoundsException. Notez la section de synchronisation de la classe javadoc pour SimpleDateFormat .

Assurez-vous qu'il n'y a aucun endroit dans votre code qui accède à des classes de threads non sécurisées comme SimpleDateFormat de manière simultanée comme dans un servlet ou un contrôleur. Vérifiez toutes les variables d'instance de vos servlets et contrôleurs pour des suspects probables.

Kyri Sarantakos
la source
2

ArrayIndexOutOfBoundsException chaque fois que cette exception arrive, cela signifie que vous essayez d'utiliser un index de tableau qui est hors de ses limites ou en termes profanes, vous demandez plus que ce que vous avez initialisé.

Pour éviter cela, assurez-vous toujours que vous ne demandez pas un index qui n'est pas présent dans le tableau, c'est-à-dire que si la longueur du tableau est 10, votre index doit être compris entre 0 et 9.

sgrpwr
la source
2

ArrayIndexOutOfBounds signifie que vous essayez d'indexer une position dans un tableau qui n'est pas allouée.

Dans ce cas:

String[] name = { "tom", "dick", "harry" };
for (int i = 0; i <= name.length; i++) {
    System.out.println(name[i]);
}
  • name.length est 3 car le tableau a été défini avec 3 objets String.
  • Lorsque vous accédez au contenu d'un tableau, la position commence à 0. Puisqu'il y a 3 éléments, cela signifierait nom [0] = "tom", nom [1] = "bite" et nom [2] = "harry
  • Lorsque vous bouclez, puisque i peut être inférieur ou égal à name.length, vous essayez d'accéder au nom [3] qui n'est pas disponible.

Pour contourner cela ...

  • Dans votre boucle for, vous pouvez faire i <nom.longueur. Cela empêcherait la boucle vers le nom [3] et s'arrêterait plutôt au nom [2]

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

  • Utilisez un pour chaque boucle

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

  • Utilisez list.forEach (action consommateur) (nécessite Java8)

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

  • Convertir le tableau en flux - c'est une bonne option si vous souhaitez effectuer des «opérations» supplémentaires sur votre tableau, par exemple filtrer, transformer le texte, convertir en une carte, etc. (nécessite Java8)

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

martinywwan
la source
1

ArrayIndexOutOfBoundsExceptionsignifie que vous essayez d'accéder à un index du tableau qui n'existe pas ou hors de la limite de ce tableau. Les index des tableaux commencent à 0 et se terminent par la longueur - 1 .

Dans ton cas

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

ArrayIndexOutOfBoundsExceptionse produit lorsque vous essayez d'accéder à l'élément indexé name.length qui n'existe pas (l'index du tableau se termine à la longueur -1). le simple remplacement de <= par <résoudrait ce problème.

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

Pour tout tableau de longueur n, les éléments du tableau auront un index de 0 à n-1.

Si votre programme essaie d'accéder à tout élément (ou mémoire) ayant un index de tableau supérieur à n-1, alors Java lèvera ArrayIndexOutOfBoundsException

Voici donc deux solutions que nous pouvons utiliser dans un programme

  1. Maintenir le décompte:

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

    Ou une autre instruction en boucle comme

    int count = 0;
    while(count < array.length) {
        System.out.println(array[count]);
        count++;
    }
  2. Un meilleur moyen d'aller avec un pour chaque boucle, dans cette méthode, un programmeur n'a pas besoin de se soucier du nombre d'éléments dans le tableau.

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

Selon votre code:

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

Si vous cochez System.out.print (name.length);

vous en aurez 3;

cela signifie que la longueur de votre nom est de 3

votre boucle est en cours d'exécution de 0 à 3, ce qui devrait être exécuté "0 à 2" ou "1 à 3"

Répondre

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

Chaque élément d'un tableau est appelé un élément et chaque élément est accessible par son index numérique. Comme indiqué dans l'illustration précédente, la numérotation commence par 0 . Le 9e élément, par exemple, serait donc accessible à l'index 8.

IndexOutOfBoundsException est levée pour indiquer qu'un index quelconque (tel qu'un tableau, une chaîne ou un vecteur) est hors de portée.

N'importe quel tableau X, est accessible de [0 à (X.length - 1)]

ZiadM
la source
1

Je vois toutes les réponses ici expliquant comment travailler avec des tableaux et comment éviter les exceptions d'index hors limites. J'évite personnellement les tableaux à tout prix. J'utilise les classes Collections, ce qui évite toute la sottise d'avoir à traiter entièrement les indices de tableau. Les constructions en boucle fonctionnent à merveille avec les collections prenant en charge du code qui est à la fois plus facile à écrire, à comprendre et à maintenir.

John Czukkermann
la source
1

Si vous utilisez la longueur d'un tableau pour contrôler l'itération d'une boucle for , n'oubliez pas que l'index du premier élément d'un tableau est 0 . Ainsi, l'index du dernier élément d'un tableau est inférieur de un à la longueur du tableau.

Sachithra Dilshan
la source
0

ArrayIndexOutOfBoundsException Le nom lui-même explique que si vous essayez d'accéder à la valeur de l'index qui est hors de la portée de la taille du tableau, ce type d'exception se produit.

Dans votre cas, vous pouvez simplement supprimer le signe égal de votre boucle for.

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

La meilleure option est d'itérer un tableau:

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

Cette erreur se produit lors de dépassements de temps de boucle de boucle. Prenons un exemple simple comme celui-ci,

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

Au début, j'ai initialisé un tableau comme 'numberArray'. puis, certains éléments du tableau sont imprimés à l'aide de la boucle for. Lorsque la boucle s'exécute en temps «i», imprimez l'élément (numberArray [i + 1] .. (lorsque la valeur i est 1, l'élément numberArray [i + 1] est imprimé.) .. Supposons que, lorsque i = (numberArray. length-2), le dernier élément du tableau est imprimé..Lorsque la valeur 'i' va à (numberArray.length-1), aucune valeur pour l'impression..À ce stade, 'ArrayIndexOutOfBoundsException' se produit. J'espère que vous pourriez obtenir idée.Merci!

GT_hash
la source
0

Vous pouvez utiliser Facultatif dans un style fonctionnel pour éviter NullPointerExceptionet 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);
}

Production:

AAA
NO_DATA
CCC
NO_DATA
Andrey Lavrukhin
la source
-4

Vous ne pouvez pas itérer ou stocker plus de données que la longueur de votre tableau. Dans ce cas, vous pourriez faire comme ceci:

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

Ou ca:

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