¿Qué causa una java.lang.ArrayIndexOutOfBoundsException y cómo puedo prevenirla?

298

¿Qué ArrayIndexOutOfBoundsExceptionsignifica y cómo me deshago de él?

Aquí hay una muestra de código que desencadena la excepción:

String[] names = { "tom", "bob", "harry" };
for (int i = 0; i <= names.length; i++) {
    System.out.println(names[i]);
}
Aaron
fuente
1
En referencia a la última pregunta, el código sería útil. ¿Está accediendo a la matriz con un índice conocido o tiene que comenzar a depurar para descubrir cómo se calcula el índice cuando se produce el error?
justkt
43
Reemplace i <= name.lengthcon i < name.length- o mejor, escriba un bucle for mejorado. ( for (String aName : name) { ... })
Jean Hominal
1
significa que desea obtener el elemento de la matriz que no existe, 'i <= name.length' significa que desea obtener la longitud del elemento + 1; no existe.
gbk

Respuestas:

296

Su primer puerto de escala debe ser la documentación que lo explica razonablemente claro:

Lanzado para indicar que se ha accedido a una matriz con un índice ilegal. El índice es negativo o mayor o igual que el tamaño de la matriz.

Así por ejemplo:

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

En cuanto a cómo evitarlo ... um, no hagas eso. Tenga cuidado con sus índices de matriz.

Un problema con el que la gente a veces se encuentra es pensar que las matrices están indexadas en 1, por ejemplo

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

Eso perderá el primer elemento (índice 0) y generará una excepción cuando el índice sea 5. Los índices válidos aquí son 0-4 inclusive. La fordeclaración correcta e idiomática aquí sería:

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

(Eso supone que necesita el índice, por supuesto. Si puede utilizar el bucle for mejorado, hágalo).

Jon Skeet
fuente
1
Yo añadiría que para las matrices multidimensionales que podrían tener una forma arbitraria en Java, los bucles anidados deben comprobar si la longitud subconjunto relevante: 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];
}

Ver también:


Actualización : según su fragmento de código,

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

El índice incluye la longitud de la matriz. Esto está fuera de los límites. Necesitas reemplazar <=por <.

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

De este excelente artículo: ArrayIndexOutOfBoundsException en for loop

Para decirlo brevemente:

En la última iteración de

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

iserá igual a name.lengthun índice ilegal, ya que los índices de matriz están basados ​​en cero.

Tu código debería leer

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

Significa que está intentando acceder a un índice de una matriz que no es válida ya que no está entre los límites.

Por ejemplo, esto inicializaría una matriz entera primitiva con el límite superior 4.

int intArray[] = new int[5];

Los programadores cuentan desde cero. Entonces, por ejemplo, arrojaría un ArrayIndexOutOfBoundsExceptioncomo el límite superior es 4 y no 5.

intArray[5];
Octavian A. Damiean
fuente
44
Los límites son los límites dentro del rango. es decir; 0-5
John Giotta
11

Para evitar una excepción de índice de matriz fuera de límites, se debe usar la instrucción mejoradafor dónde y cuándo pueden.

La motivación principal (y el caso de uso) es cuando está iterando y no requiere pasos de iteración complicados. Se podría no ser capaz de utilizar un enhanced- forpara mover hacia atrás en una matriz o solamente iterar sobre todos los demás elementos.

Se garantiza que no se quedará sin elementos para iterar al hacer esto, y su ejemplo [corregido] se convierte fácilmente.

El código a continuación:

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

... es equivalente a esto:

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

¿Qué causa ArrayIndexOutOfBoundsException?

Si piensa en una variable como un "cuadro" donde puede colocar un valor, una matriz es una serie de cuadros colocados uno al lado del otro, donde el número de cuadros es un entero finito y explícito.

Crear una matriz como esta:

final int[] myArray = new int[5]

crea una fila de 5 cajas, cada una con un int. Cada una de las cajas tiene un índice, una posición en la serie de cajas. Este índice comienza en 0 y termina en N-1, donde N es el tamaño de la matriz (el número de cajas).

Para recuperar uno de los valores de esta serie de cuadros, puede consultarlo a través de su índice, así:

myArray[3]

Lo que le dará el valor del cuarto cuadro de la serie (ya que el primer cuadro tiene el índice 0).

Un problema ArrayIndexOutOfBoundsExceptionse produce al intentar recuperar un "cuadro" que no existe, al pasar un índice que es más alto que el índice del último "cuadro", o negativo.

Con mi ejemplo en ejecución, estos fragmentos de código producirían una excepción:

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

Como evitar ArrayIndexOutOfBoundsException

Para prevenir ArrayIndexOutOfBoundsException, hay algunos puntos clave a considerar:

Bucle

Al recorrer una matriz, asegúrese siempre de que el índice que está recuperando es estrictamente más pequeño que la longitud de la matriz (el número de cajas). Por ejemplo:

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

Observe el <, nunca mezcle un =allí.

Es posible que desee tener la tentación de hacer algo como esto:

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

Solo no lo hagas. Apéguese al anterior (si necesita usar el índice) y le ahorrará mucho dolor.

Donde sea posible, use foreach:

for (int value : myArray) {

De esta manera, no tendrá que pensar en índices en absoluto.

Al hacer un bucle, haga lo que haga, NUNCA cambie el valor del iterador de bucle (aquí:) i. El único lugar donde esto debería cambiar el valor es mantener el ciclo en marcha. Cambiarlo de otra manera es solo arriesgarse a una excepción, y en la mayoría de los casos no es necesario.

Recuperación / actualización

Al recuperar un elemento arbitrario de la matriz, siempre verifique que sea un índice válido contra la longitud de la matriz:

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
fuente
6

En su código, ha accedido a los elementos desde el índice 0 hasta la longitud de la matriz de cadenas. name.lengthda el número de objetos de cadena en su matriz de objetos de cadena, es decir, 3, pero solo puede acceder hasta el índice 2 name[2], porque se puede acceder a la matriz desde el índice 0 hasta name.length - 1donde obtiene el name.lengthnúmero de objetos.

Incluso mientras usa un forbucle, ha comenzado con el índice cero y debe terminar con name.length - 1. En una matriz a [n] puede acceder desde [0] a a [n-1].

Por ejemplo:

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

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

En tu caso:

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

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

Para su matriz dada, la longitud de la matriz es 3 (es decir, name.length = 3). Pero como almacena el elemento a partir del índice 0, tiene el índice máximo 2.

Entonces, en lugar de 'i ** <= name.length', debe escribir 'i <** name.length' para evitar 'ArrayIndexOutOfBoundsException'.

nIKHIL
fuente
3

Esto en cuanto a esta simple pregunta, pero solo quería destacar una nueva característica en Java que evitará todas las confusiones sobre la indexación en matrices, incluso para principiantes. Java-8 ha abstraído la tarea de iterar para usted.

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

Cual es el beneficio? Bueno, una cosa es la legibilidad como el inglés. En segundo lugar, no necesita preocuparse por elArrayIndexOutOfBoundsException

Satyendra Kumar
fuente
3

Usted se ArrayIndexOutOfBoundsExceptiondebe debido a i<=name.lengthparte. name.lengthdevuelve la longitud de la cadena name, que es 3. Por lo tanto, cuando intenta acceder name[3], es ilegal y produce una excepción.

Código resuelto:

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

Está definido en la especificación del lenguaje Java :

El public finalcampo length, que contiene el número de componentes de la matriz. lengthpuede ser positivo o cero

roottraveller
fuente
3

Excepción de índice de matriz fuera de límites

Así es como se ve este tipo de excepción cuando se lanza en Eclipse. El número en rojo significa el índice al que intentó acceder. Entonces el código se vería así:

myArray[5]

El error se produce cuando intenta acceder a un índice que no existe en esa matriz. Si una matriz tiene una longitud de 3,

int[] intArray = new int[3];

entonces los únicos índices válidos son:

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

Si una matriz tiene una longitud de 1,

int[] intArray = new int[1];

entonces el único índice válido es:

intArray[0]

Cualquier número entero igual a la longitud de la matriz, o más grande que él: está fuera de los límites.

Cualquier número entero menor que 0: está fuera de los límites;

PD: Si busca comprender mejor las matrices y hacer algunos ejercicios prácticos, aquí hay un video: tutorial sobre matrices en Java

Johny
fuente
3

Para las matrices multidimensionales, puede ser complicado asegurarse de acceder a la lengthpropiedad de la dimensión correcta. Tome el siguiente código, por ejemplo:

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

Cada dimensión tiene una longitud diferente, por lo que el error sutil es que los bucles medio e interno usan la lengthpropiedad de la misma dimensión (porque a[i].lengthes lo mismo que a[j].length).

En cambio, el bucle interno debe usar a[i][j].length(o a[0][0].length, por simplicidad).

Bill el lagarto
fuente
Se agregó un ejemplo de código de ¿Por qué mi bucle for no funciona cuando cambio la condición (matrices multidimensionales)? ya que esta pregunta se usa como un objetivo engañado para cualquier pregunta relacionada con ArrayIndexOutOfBoundsException.
Bill the Lizard
2

El caso más común que he visto para ArrayIndexOutOfBoundsExceptions aparentemente misteriosas, es decir, aparentemente no causado por su propio código de manejo de matriz, es el uso simultáneo de SimpleDateFormat. Particularmente en un servlet o controlador:

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 dos hilos ingresan el método SimplateDateFormat.parse () juntos, probablemente verá una excepción ArrayIndexOutOfBoundsException. Tenga en cuenta la sección de sincronización de la clase javadoc para SimpleDateFormat .

Asegúrese de que no haya lugar en su código que esté accediendo a clases inseguras de subprocesos como SimpleDateFormat de manera concurrente como en un servlet o controlador. Verifique todas las variables de instancia de sus servlets y controladores para detectar posibles sospechosos.

Kyri Sarantakos
fuente
2

ArrayIndexOutOfBoundsException siempre que se presente esta excepción, significa que está tratando de usar un índice de matriz que está fuera de sus límites o en términos simples que está solicitando más de lo que ha inicializado.

Para evitar esto, asegúrese siempre de que no está solicitando un índice que no está presente en la matriz, es decir, si la longitud de la matriz es 10, entonces su índice debe oscilar entre 0 y 9

sgrpwr
fuente
2

ArrayIndexOutOfBounds significa que está intentando indexar una posición dentro de una matriz que no está asignada.

En este caso:

String[] name = { "tom", "dick", "harry" };
for (int i = 0; i <= name.length; i++) {
    System.out.println(name[i]);
}
  • name.length es 3 ya que la matriz se ha definido con 3 objetos String.
  • Al acceder al contenido de una matriz, la posición comienza desde 0. Como hay 3 elementos, significaría nombre [0] = "tom", nombre [1] = "dick" y nombre [2] = "harry
  • Cuando bucle, ya que puede ser menor que o igual a name.length, que está intentando acceder nombre [3], que no está disponible.

Para evitar esto ...

  • En su bucle for, puede hacer i <name.length. Esto evitaría bucles al nombre [3] y en su lugar se detendría en el nombre [2]

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

  • Use a para cada bucle

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

  • Use list.forEach (Acción del consumidor) (requiere Java8)

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

  • Convertir matriz a transmisión: esta es una buena opción si desea realizar 'operaciones' adicionales a su matriz, por ejemplo, filtrar, transformar el texto, convertir a un mapa, etc. (requiere Java8)

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

martinywwan
fuente
1

ArrayIndexOutOfBoundsExceptionsignifica que está intentando acceder a un índice de la matriz que no existe o está fuera del límite de esta matriz. Los índices de matriz comienzan desde 0 y terminan en longitud - 1 .

En tu caso

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

ArrayIndexOutOfBoundsExceptionsucede cuando intenta acceder al elemento indexado name.length que no existe (el índice de matriz termina en longitud -1). simplemente reemplazando <= con <resolvería este problema.

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

Para cualquier matriz de longitud n, los elementos de la matriz tendrán un índice de 0 a n-1.

Si su programa está intentando acceder a cualquier elemento (o memoria) que tenga un índice de matriz mayor que n-1, entonces Java arrojará ArrayIndexOutOfBoundsException

Aquí hay dos soluciones que podemos usar en un programa

  1. Recuento de mantenimiento:

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

    O alguna otra declaración de bucle como

    int count = 0;
    while(count < array.length) {
        System.out.println(array[count]);
        count++;
    }
  2. Una mejor manera de ir con un para cada bucle, en este método, un programador no tiene necesidad de preocuparse por el número de elementos en la matriz.

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

De acuerdo a su código:

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

Si marca System.out.print (name.length);

obtendrás 3;

eso significa que la longitud de tu nombre es 3

su bucle se ejecuta de 0 a 3, que debería ejecutar "0 a 2" o "1 a 3"

Responder

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

Cada elemento de una matriz se llama elemento y se accede a cada elemento por su índice numérico. Como se muestra en la ilustración anterior, la numeración comienza con 0 . Por lo tanto, se accedería al noveno elemento, por ejemplo, en el índice 8.

IndexOutOfBoundsException se genera para indicar que un índice de algún tipo (como una matriz, una cadena o un vector) está fuera de rango.

Se puede acceder a cualquier matriz X desde [0 a (X.length - 1)]

ZiadM
fuente
1

Veo todas las respuestas aquí explicando cómo trabajar con matrices y cómo evitar las excepciones de índice fuera de límites. Yo personalmente evito las matrices a toda costa. Utilizo las clases de Colecciones, lo que evita toda la tontería de tener que lidiar con los índices de matriz por completo. Las construcciones de bucle funcionan maravillosamente con colecciones que soportan código que es más fácil de escribir, comprender y mantener.

John Czukkermann
fuente
1

Si usa la longitud de una matriz para controlar la iteración de un bucle for , recuerde siempre que el índice del primer elemento de una matriz es 0 . Entonces, el índice del último elemento en una matriz es uno menos que la longitud de la matriz.

Sachithra Dilshan
fuente
0

ArrayIndexOutOfBoundsException El nombre mismo explica que si intenta acceder al valor en el índice que está fuera del alcance del tamaño de la matriz, se produce ese tipo de excepción.

En su caso, puede eliminar el signo igual del bucle for.

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

La mejor opción es iterar una matriz:

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

Este error se produce en tiempos de límite excesivos del ciclo de ejecución. Consideremos un ejemplo simple como este,

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

Al principio, he inicializado una matriz como 'numberArray'. luego, algunos elementos de la matriz se imprimen usando for loop. Cuando el ciclo está ejecutando el tiempo 'i', imprima el elemento (númeroArray [i + 1] .. (cuando el valor de i es 1, se imprime el elemento numberArray [i + 1]). Suponga que, cuando i = (númeroArray. longitud-2), se imprime el último elemento de la matriz ... Cuando el valor 'i' va a (númeroArray.length-1), no hay valor para imprimir ... En ese punto, se produce 'ArrayIndexOutOfBoundsException'. Espero que pueda obtener idea.gracias!

GT_hash
fuente
0

Puede usar Opcional en estilo funcional para evitar NullPointerExceptiony 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);
}

Salida:

AAA
NO_DATA
CCC
NO_DATA
Andrey Lavrukhin
fuente
-4

No podría iterar o almacenar más datos que la longitud de su matriz. En este caso, podrías hacer así:

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

O esto:

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