¿Cómo puedo evitar ArrayIndexOutOfBoundsException o IndexOutOfBoundsException? [duplicar]
Si su pregunta es: Recibo un error java.lang.ArrayIndexOutOfBoundsException
en mi código y no entiendo por qué sucede, ¿qué significa y cómo puedo evitarlo?
Esta pretende ser la colección canónica más completa de información sobre este
java.lang.ArrayIndexOutOfBoundsException
tema, así como sobrejava.lang.IndexOutOfBoundsException
.
Hay muchas preguntas como esta y todas tienen respuestas vagas sin código o, en su mayoría, son extremadamente específicas y están localizadas en la pregunta en cuestión y no abordan la causa raíz, que es exactamente la misma en todos los casos.
Si ve uno que se incluye en este caso general, en lugar de responderlo con más contenido especializado duplicado, márquelo como un duplicado de este.
¿Qué es java.lang.ArrayIndexOutOfBoundsException/java.lang.IndexOutOfBoundsException?
El JavaDoc dice brevemente:
Se lanza 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.
¿Qué causa que esto suceda?
Esta excepción significa que ha intentado acceder a un índice en una matriz o en una lista respaldada por matrices y ese índice no existe.
Java utiliza
0
índices basados. Eso significa que todos los índices comienzan con0
el índice del primer elemento si contiene algún elemento.
El IndexOutOfBoundsException
mensaje es muy explícito y suele adoptar la forma de:
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
¿Dónde Index
está el índice que solicitó y que no existe y Size
es la longitud de la estructura en la que estaba indexando?
Como puede ver, Size: 1
significa que el único índice válido es 0
y usted estaba preguntando qué había en el índice 1
.
Por ejemplo, si tiene un conjunto
Array
de objetos o tipos primitivos, los índices válidos son0
,.length - 1
en el siguiente ejemplo los índices válidos serían0, 1, 2, 3,
.
final String days[] { "Sunday", "Monday", "Tuesday" }
System.out.println(days.length); // 3
System.out.println(days[0]); // Sunday
System.out.println(days[1]); // Monday
System.out.println(days[2]); // Tuesday
System.out.println(days[3]); // java.lang.ArrayIndexOutOfBoundsException
Esto también se aplica a ArrayList
cualquier otra Collection
clase que pueda estar respaldada por un índice Array
y permita el acceso directo al mismo.
¿Cómo evitar el java.lang.ArrayIndexOutOfBoundsException
/ java.lang.IndexOutOfBoundsException
?
Al acceder directamente por índice:
Esto utiliza Guava para convertir la
int[]
matriz primitiva sin formato en un archivoImmutableList<Integer>
. Luego usa laIterables
clase para obtener de forma segura el valor en un índice particular y proporciona un valor predeterminado cuando ese índice no existe. Aquí elegí-1
indicar un valor de índice no válido.
final List<Integer> toTen = ImmutableList.copyOf(Ints.asList(ints));
System.out.println(Iterables.get(toTen, 0, -1));
System.out.println(Iterables.get(toTen, 100, -1));
Si no puede usar Guava por alguna razón, es fácil implementar su propia función para hacer lo mismo.
private static <T> T get(@Nonnull final Iterable<T> iterable, final int index, @Nonnull final T missing)
{
if (index < 0) { return missing; }
if (iterable instanceof List)
{
final List<T> l = List.class.cast(iterable);
return l.size() <= index ? l.get(index) : missing;
}
else
{
final Iterator<T> iterator = iterable.iterator();
for (int i = 0; iterator.hasNext(); i++)
{
final T o = iterator.next();
if (i == index) { return o; }
}
return missing;
}
}
Al iterar:
Estas son las formas idiomáticas de iterar sobre un archivo sin formato
Array
si necesita conocer el índice y el valor:Esto es susceptible a errores puntuales que son las causas principales de
java.lang.ArrayIndexOutOfBoundsException
:
Usando un bucle tradicional for - next :
final int ints[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (int i = 0; i < ints.length; i++)
{
System.out.format("index %d = %d", i, ints[i]);
}
Usando un bucle mejorado para cada uno :
Esta es la forma idiomática de iterar sobre un archivo raw
Array
con el bucle for mejorado si no necesita conocer el índice real:
for (final int i : ints)
{
System.out.format("%d", i);
System.out.println();
}
Usando un Iterador <T> de tipo seguro:
Esta es la forma segura de iterar sobre un archivo sin formato
Array
con el bucle for mejorado y realizar un seguimiento del índice actual y evitar la posibilidad de encontrar un archivojava.lang.ArrayIndexOutOfBoundsException
.Esto utiliza Guava para convertir fácilmente el archivo
int[]
en algoIterable
que cada proyecto debería incluir.
final Iterator<Integer> it = Ints.asList(ints).iterator();
for (int i = 0; it.hasNext(); i++)
{
System.out.format("index %d = %d", i, it.next());
}
Si no puedes usar guayaba o la tuya int[]
es enorme, puedes enrollar la tuya ImmutableIntArrayIterator
como tal:
public class ImmutableIntArrayIterator implements Iterator<Integer>
{
private final int[] ba;
private int currentIndex;
public ImmutableIntArrayIterator(@Nonnull final int[] ba)
{
this.ba = ba;
if (this.ba.length > 0) { this.currentIndex = 0; }
else { currentIndex = -1; }
}
@Override
public boolean hasNext() { return this.currentIndex >= 0 && this.currentIndex + 1 < this.ba.length; }
@Override
public Integer next()
{
this.currentIndex++;
return this.ba[this.currentIndex];
}
@Override
public void remove() { throw new UnsupportedOperationException(); }
}
Y usa el mismo código que usarías con Guava.
Si es absolutamente necesario tener el ordinal del elemento, la siguiente es la forma más segura de hacerlo.
// Assume 'los' is a list of Strings
final Iterator<String> it = los.iterator();
for (int i = 0; it.hasNext(); i++)
{
System.out.format("index %d = %s", i, it.next());
}
Esta técnica funciona para todos los Iterables . No es un análisis de índice , pero le brinda la posición actual en la iteración incluso para cosas que no tienen un índice nativo .
La forma más segura:
La mejor manera es usar siempre ImmutableLists / Set / Maps de Guava también:
final List<Integer> ili = ImmutableList.copyOf(Ints.asList(ints));
final Iterator<Integer> iit = ili.iterator();
for (int i = 0; iit.hasNext(); i++)
{
System.out.format("index %d = %d", i, iit.next());
}
Resumen:
Es difícil trabajar con matrices sin formato y debe evitarse en la mayoría de los casos. Son susceptibles a errores únicos, a veces sutiles , que han afectado a los nuevos programadores incluso desde los días de BASIC .
Los modismos modernos de Java utilizan colecciones seguras de tipo adecuado y, si es posible, evitan el uso de estructuras de matriz sin formato.
Actualmente se prefieren los tipos inmutables en casi todos los casos.
Guava es un conjunto de herramientas indispensable para el desarrollo moderno de Java.