web-dev-qa-db-fra.com

Quelles sont les causes d'une exception Java.lang.ArrayIndexOutOfBoundsException et comment puis-je l'éviter?

Que signifie ArrayIndexOutOfBoundsException et comment puis-je m'en débarrasser? 

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

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

Votre première escale devrait être la documentation qui l'explique assez clairement:

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

Donc par exemple:

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

Pour ce qui est de l'éviter, ne faites pas ça. Soyez prudent avec vos index de tableau.

Un problème que rencontrent parfois les gens 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 index est 5. Les index valides ici sont 0-4 inclus. La déclaration correcte et idiomatique for serait ici:

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

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

247
Jon Skeet
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:


Update: selon l'extrait de code, 

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

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

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

Pour le dire brièvement:

Dans la dernière itération de

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

i sera égal à name.length qui est un index illégal, car les index de tableau sont basés sur zéro.

Votre code devrait lire

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

Cela signifie que vous essayez d'accéder à un index d'un tableau qui n'est pas valide car il ne se trouve 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. Donc, par exemple, cela jetterait une ArrayIndexOutOfBoundsException puisque la limite supérieure est 4 et non 5.

intArray[5];
14
Octavian Damiean

Quelles sont les causes ArrayIndexOutOfBoundsException?

Si vous considérez une variable comme une "boîte" dans laquelle vous pouvez placer une valeur, un tableau est une série de boîtes placées l'une à côté de l'autre, le nombre de boîtes étant un entier fini et explicite.

Créer un tableau comme ceci:

final int[] myArray = new int[5]

crée une rangée de 5 cases, chacune contenant une int. Chacune des cases a un index, une position dans la série de 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 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'indice 0).

Une ArrayIndexOutOfBoundsException est provoquée en essayant de rentrer une "boîte" qui n'existe pas, en transmettant un index supérieur à celui de la dernière "boîte" ou négatif.

Avec mon exemple courant, 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 d'éviter ArrayIndexOutOfBoundsException, certains points essentiels sont à prendre en compte:

en 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]

Juste ne pas. Tenez-vous-en à celui ci-dessus (si vous avez besoin d’index) et vous éviterez beaucoup de douleur.

Si possible, utilisez foreach:

for (int value : myArray) {

De cette façon, vous n'aurez plus à penser aux index.

Quoi que vous fassiez en boucle, ne changez JAMAIS la valeur de l’itérateur de boucle (ici: i). Le seul endroit où cela devrait changer de valeur est de continuer la boucle. Le changer autrement risquerait de créer une exception et, dans la plupart des cas, il ne serait pas nécessaire.

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

Pour éviter une exception hors-tableau d'indice de tableau, vous devez utiliser l'instruction enhanced -for où et quand ils le peuvent.

La principale motivation (et le cas d'utilisation) est lorsque vous effectuez une itération et que vous ne nécessitez aucune étape d'itération compliquée. Not pourrait utiliser une variable -for améliorée pour revenir en arrière dans un tableau ou effectuer une itération sur tous les autres éléments.

Vous êtes assuré de ne pas manquer d'éléments sur lesquels itérer, 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");
}

... est équivalent à ceci:

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

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

Même si vous utilisez une boucle for, vous avez commencé avec l'index zéro et vous devez terminer par name.length - 1. Dans un tableau a [n], vous pouvez accéder au formulaire a [0] à a [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');
}
4

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

Ainsi, au lieu de 'i ** <= name.length', vous devriez écrire 'i <** name.length' pour éviter 'ArrayIndexOutOfBoundsException'.

3
nIKHIL

Voilà pour cette question simple, mais je voulais simplement souligner une nouvelle fonctionnalité de Java qui évitera toute confusion au sujet de l'indexation dans les tableaux, même pour les débutants. Java-8 a résumé la tâche d'itération 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 la ArrayIndexOutOfBoundsException

2
Satyendra Kumar

 Array index out of bounds exception

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

myArray[5]

L'erreur est renvoyé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 nombre entier égal à la longueur du tableau ou supérieur à celui-ci: hors limites.

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

P.S .: Si vous cherchez à mieux comprendre les tableaux et faites des exercices pratiques, voici une vidéo: tutoriel sur les tableaux en Java

2
Ion

Vous obtenez ArrayIndexOutOfBoundsException en raison de la partie i<=name.length. name.length renvoie la longueur de la chaîne name, qui est 3. Par conséquent, lorsque vous essayez d'accéder à name[3], il est illégal et génère 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 champ public finallength, qui contient le nombre de composants du tableau. length peut être positif ou nul.

2
roottraveller

ArrayIndexOutOfBoundsException chaque fois que cette exception survient, cela signifie que vous essayez d'utiliser un index de tableau qui est hors de ses limites ou en termes simples que 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 un tableau, c'est-à-dire si la longueur du tableau est 10, votre index doit être compris entre 0 et 9.

1
sgrpwr

Si vous utilisez la longueur d'un tableau pour contrôler l'itération d'une boucle pour , souvenez-vous toujours que l'index du premier élément d'un tableau est 0 . Donc, l'index du dernier élément d'un tableau est inférieur de un à la longueur du tableau.

1
Sachithra Dilshan

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 obtiendrez 3;

cela signifie que la longueur de votre nom est 3

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

Réponse

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

Le cas le plus courant que j’ai vu pour des exceptions apparemment mystérieuses, ArrayIndexOutOfBoundsExceptions, c’est-à-dire qui ne soit apparemment pas causé 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 dans 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’existe pas dans votre code d’accès simultané aux classes non protégées de threads telles que SimpleDateFormat, comme dans un servlet ou un contrôleur. Vérifiez toutes les variables d'instance de vos servlets et contrôleurs pour les suspects potentiels.

1
Kyri Sarantakos

Pour les tableaux multidimensionnels, il peut être difficile de vous assurer que vous accédez à la propriété length de la bonne dimension. Prenez le code suivant par exemple:

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 ayant une longueur différente, le bogue le plus complexe est que les boucles centrale et interne utilisent la propriété length de la même dimension (car a[i].length est identique à a[j].length).

Au lieu de cela, la boucle interne doit utiliser a[i][j].length (ou a[0][0].length, par souci de simplicité).

1
Bill the Lizard

ArrayIndexOutOfBoundsException signifie que vous essayez d'accéder à un index du tableau qui n'existe pas ou qui n'est pas lié à ce tableau. Les index de tableau commencent par 0 et se terminent par 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
}

ArrayIndexOutOfBoundsException survient lorsque vous essayez d'accéder à l'élément indexé name.length qui n'existe pas (l'index d'un tableau se termine par la longueur -1). remplacer simplement <= 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
}
0
adn.911

Chaque élément d'un tableau s'appelle 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 9ème élément, par exemple, serait donc accessible à l'index 8.

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

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

0
ZiadM

ArrayIndexOutOfBoundsException name explique lui-même 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 consiste à itérer un tableau:

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

Cette erreur survient lors de périodes de dépassement de boucle en 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 en tant que 'numberArray'. ensuite, certains éléments du tableau sont imprimés en utilisant for for. Lorsque la boucle est en cours d'exécution, affiche l'élément (numberArray [i + 1] .. (lorsque i est égal à 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' est définie sur (numberArray.length-1), aucune valeur n'est indiquée pour l'impression..Dans ce point, 'ArrayIndexOutOfBoundsException' se produit.J'espère que vous pourrez obtenir idée.merci!

0
GT_hash

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

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

Donc, voici deux solutions que nous pouvons utiliser dans un programme

  1. Maintenir le compte:

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

    Ou une autre déclaration en boucle comme

    int count = 0;
    while(count < array.length) {
        System.out.println(array[count]);
        count++;
    }
    
  2. Une meilleure solution consiste à utiliser une boucle pour chaque boucle. Dans cette méthode, un programmeur n’a pas à se préoccuper du nombre d’éléments dans le tableau.

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

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

0
John Czukkermann