O que causa uma java.lang.ArrayIndexOutOfBoundsException e como evito isso?

298

O que ArrayIndexOutOfBoundsExceptionsignifica e como me livrar dele?

Aqui está um exemplo de código que aciona a exceção:

String[] names = { "tom", "bob", "harry" };
for (int i = 0; i <= names.length; i++) {
    System.out.println(names[i]);
}
Aaron
fonte
1
Em referência à última pergunta, o código seria útil. Você está acessando a matriz com um índice conhecido ou precisa iniciar a depuração para descobrir como o índice é calculado quando o erro ocorre?
justkt
43
Substitua i <= name.lengthpor i < name.length- ou melhor, escreva um loop for aprimorado. ( for (String aName : name) { ... })
Jean Hominal
1
significa que você deseja obter o elemento da matriz que não existe, 'i <= name.length' significa que você deseja obter o comprimento do elemento + 1 - ele não existe.
Gbk

Respostas:

296

Seu primeiro porto de escala deve ser a documentação que explica razoavelmente claramente:

Lançada para indicar que uma matriz foi acessada com um índice ilegal. O índice é negativo ou maior que ou igual ao tamanho da matriz.

Então, por exemplo:

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

Quanto a como evitá-lo ... hum, não faça isso. Tenha cuidado com seus índices de matriz.

Um problema que as pessoas às vezes encontram é pensar que as matrizes são indexadas 1, por exemplo

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

Isso perderá o primeiro elemento (índice 0) e lançará uma exceção quando o índice for 5. Os índices válidos aqui são de 0 a 4, inclusive. A fordeclaração idiomática correta aqui seria:

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

(Supondo que você precise do índice, é claro. Se você pode usar o loop for aprimorado, faça isso).

Jon Skeet
fonte
1
Eu acrescentaria que, para arrays multidimensionais que podem ter uma forma arbitrária em Java, os loops aninhados deve verificar o comprimento subarray 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];
}

Veja também:


Atualização : conforme seu snippet de código,

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

O índice inclui o comprimento da matriz. Isso está fora dos limites. Você precisa substituir <=por <.

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

Deste excelente artigo: ArrayIndexOutOfBoundsException in for loop

Para resumir:

Na última iteração de

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

iserá igual a name.lengthum índice ilegal, pois os índices da matriz são baseados em zero.

Seu código deve ler

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

Isso significa que você está tentando acessar um índice de uma matriz que não é válida, pois não está entre os limites.

Por exemplo, isso inicializaria uma matriz inteira primitiva com o limite superior 4.

int intArray[] = new int[5];

Os programadores contam a partir de zero. Portanto, isso, por exemplo, lançaria um ArrayIndexOutOfBoundsExceptioncomo o limite superior é 4 e não 5.

intArray[5];
Otaviano A. Damiean
fonte
4
Limites são os limites dentro do alcance. ie; 0-5
John Giotta
11

Para evitar uma exceção fora dos limites do índice de matriz, deve-se usar a instrução aprimoradafor onde e quando puderem.

A principal motivação (e caso de uso) é quando você está iterando e não precisa de etapas complicadas da iteração. Você não seria capaz de usar um aprimorado forpara retroceder em uma matriz ou apenas iterar em todos os outros elementos.

Você está garantido para não ficar sem elementos para iterar ao fazer isso, e seu exemplo [corrigido] é facilmente convertido.

O código abaixo:

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

... é equivalente a isso:

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

O que causa ArrayIndexOutOfBoundsException?

Se você pensa em uma variável como uma "caixa" onde pode colocar um valor, uma matriz é uma série de caixas colocadas próximas uma da outra, em que o número de caixas é um número inteiro finito e explícito.

Criando uma matriz como esta:

final int[] myArray = new int[5]

cria uma linha de 5 caixas, cada uma segurando um int. Cada uma das caixas tem um índice, uma posição na série de caixas. Esse índice começa em 0 e termina em N-1, onde N é o tamanho da matriz (o número de caixas).

Para recuperar um dos valores dessa série de caixas, você pode consultá-lo através de seu índice, assim:

myArray[3]

O que fornecerá o valor da quarta caixa da série (já que a primeira caixa possui o índice 0).

Um ArrayIndexOutOfBoundsExceptioné causado pela tentativa de recuperar uma "caixa" que não existe, passando um índice maior que o índice da última "caixa" ou negativo.

No meu exemplo em execução, esses trechos de código produziriam uma exceção:

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 evitar ArrayIndexOutOfBoundsException, há alguns pontos-chave a serem considerados:

Looping

Ao percorrer uma matriz, sempre verifique se o índice que você está recuperando é estritamente menor que o comprimento da matriz (o número de caixas). Por exemplo:

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

Observe o <, nunca misture um =lá ..

Você pode querer ser tentado a fazer algo assim:

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

Apenas não. Atenha-se ao indicado acima (se você precisar usar o índice) e isso poupará muita dor.

Sempre que possível, use foreach:

for (int value : myArray) {

Dessa forma, você não precisará pensar em índices.

Ao fazer o loop, faça o que fizer, NUNCA altere o valor do iterador do loop (aqui:) i. O único lugar em que isso deve alterar o valor é manter o loop funcionando. Mudá-lo de outra maneira está apenas arriscando uma exceção e, na maioria dos casos, não é necessário.

Recuperação / atualização

Ao recuperar um elemento arbitrário da matriz, sempre verifique se é um índice válido em relação ao comprimento da 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
fonte
6

No seu código, você acessou os elementos do índice 0 até o comprimento da matriz de cadeias. name.lengthfornece o número de objetos de seqüência de caracteres em sua matriz de objetos de seqüência de caracteres, ou seja, 3, mas você pode acessar apenas até o índice 2 name[2], porque a matriz pode ser acessada do índice 0 até o local name.length - 1onde você obtém o name.lengthnúmero de objetos.

Mesmo usando um forloop, você começou com o índice zero e deve terminar com name.length - 1. Em uma matriz a [n] você pode acessar do formulário a [0] a um [n-1].

Por exemplo:

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

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

No seu caso:

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

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

Para sua matriz especificada, o comprimento da matriz é 3 (ou seja, name.length = 3). Mas, como armazena o elemento a partir do índice 0, possui o índice máximo 2.

Portanto, em vez de 'i ** <= name.length', você deve escrever 'i <** name.length' para evitar 'ArrayIndexOutOfBoundsException'.

nIKHIL
fonte
3

Chega de perguntas simples, mas eu só queria destacar um novo recurso em Java que evitará todas as confusões em torno da indexação em matrizes, mesmo para iniciantes. O Java-8 abstraiu a tarefa de iterar para você.

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

Qual o benefício? Bem, uma coisa é a legibilidade como o inglês. Segundo, você não precisa se preocupar com oArrayIndexOutOfBoundsException

Satyendra Kumar
fonte
3

Você está recebendo ArrayIndexOutOfBoundsExceptiondevido a i<=name.lengthparte. name.lengthretorne o comprimento da string name, que é 3. Portanto, quando você tenta acessar name[3], é ilegal e gera uma exceção.

Código resolvido:

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

É definido na especificação da linguagem Java :

O public finalcampo length, que contém o número de componentes da matriz. lengthpode ser positivo ou zero.

roottraveller
fonte
3

Índice de matriz fora dos limites de exceção

É assim que esse tipo de exceção é exibido quando lançado no Eclipse. O número em vermelho significa o índice que você tentou acessar. Portanto, o código ficaria assim:

myArray[5]

O erro é gerado quando você tenta acessar um índice que não existe nessa matriz. Se uma matriz tiver um comprimento de 3,

int[] intArray = new int[3];

os únicos índices válidos são:

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

Se uma matriz tiver um comprimento de 1,

int[] intArray = new int[1];

então o único índice válido é:

intArray[0]

Qualquer número inteiro igual ao comprimento da matriz ou maior que ele: está fora dos limites.

Qualquer número inteiro menor que 0: está fora dos limites;

PS: Se você deseja entender melhor as matrizes e fazer alguns exercícios práticos, há um vídeo aqui: tutorial sobre matrizes em Java

Johny
fonte
3

Para matrizes multidimensionais, pode ser complicado garantir o acesso à lengthpropriedade da dimensão correta. Pegue o seguinte código, por exemplo:

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 dimensão tem um comprimento diferente; portanto, o erro sutil é que os loops intermediários e internos usam a lengthpropriedade da mesma dimensão (porque a[i].lengthé a mesma que a[j].length).

Em vez disso, o loop interno deve usar a[i][j].length(ou a[0][0].length, para simplificar).

Bill the Lizard
fonte
Adicionado um exemplo de código de Por que meu loop for não funciona quando altero a condição (matrizes multidimensionais)? já que essa pergunta é usada como um destino idiota para qualquer pergunta relacionada a ArrayIndexOutOfBoundsException.
Bill o Lagarto
2

O caso mais comum que eu já vi para ArrayIndexOutOfBoundsExceptions aparentemente misterioso, ou seja, aparentemente não causado pelo seu próprio código de manipulação de array, é o uso simultâneo de SimpleDateFormat. Particularmente em um servlet ou 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"));
  }
}

Se dois threads inserirem o método SimplateDateFormat.parse () juntos, você provavelmente verá uma ArrayIndexOutOfBoundsException. Observe a seção de sincronização da classe javadoc para SimpleDateFormat .

Verifique se não há nenhum lugar no seu código que esteja acessando classes inseguras de encadeamentos, como SimpleDateFormat, de maneira simultânea, como em um servlet ou controlador. Verifique todas as variáveis ​​de instância de seus servlets e controladores quanto a possíveis suspeitos.

Kyri Sarantakos
fonte
2

ArrayIndexOutOfBoundsException sempre que essa exceção ocorre, significa que você está tentando usar um índice de matriz que está fora de seus limites ou em termos leigos que você está solicitando mais do que inicializou.

Para evitar isso, verifique sempre se você não está solicitando um índice que não esteja presente na matriz, ou seja, se o comprimento da matriz for 10, seu índice deverá variar entre 0 e 9

sgrpwr
fonte
2

ArrayIndexOutOfBounds significa que você está tentando indexar uma posição em uma matriz que não está alocada.

Nesse caso:

String[] name = { "tom", "dick", "harry" };
for (int i = 0; i <= name.length; i++) {
    System.out.println(name[i]);
}
  • name.length é 3, pois a matriz foi definida com 3 objetos String.
  • Ao acessar o conteúdo de uma matriz, a posição começa em 0. Como existem 3 itens, significaria nome [0] = "tom", nome [1] = "pau" e nome [2] = "harry
  • Quando você faz um loop, como eu posso ser menor ou igual a name.length, você está tentando acessar o nome [3] que não está disponível.

Para contornar isso ...

  • No seu loop for, você pode fazer i <name.length. Isso impediria o loop para nomear [3] e, em vez disso, pararia no nome [2]

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

  • Use a para cada loop

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

  • Use list.forEach (ação do consumidor) (requer Java8)

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

  • Converter matriz em fluxo - esta é uma boa opção se você deseja executar 'operações' adicionais em sua matriz, por exemplo, filtrar, transformar o texto, converter em um mapa etc. (requer Java8)

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

martinywwan
fonte
1

ArrayIndexOutOfBoundsExceptionsignifica que você está tentando acessar um índice da matriz que não existe ou está fora dos limites dessa matriz. Os índices da matriz começam em 0 e terminam no comprimento - 1 .

No seu caso

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

ArrayIndexOutOfBoundsExceptionacontece quando você está tentando acessar o elemento indexado name.length que não existe (o índice da matriz termina no comprimento -1). apenas substituir <= por <resolveria esse 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
fonte
1

Para qualquer matriz de comprimento n, os elementos da matriz terão um índice de 0 a n-1.

Se seu programa está tentando acessar qualquer elemento (ou memória) com índice de matriz maior que n-1, o Java lançará ArrayIndexOutOfBoundsException

Então, aqui estão duas soluções que podemos usar em um programa

  1. Manter a contagem:

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

    Ou alguma outra declaração em loop, como

    int count = 0;
    while(count < array.length) {
        System.out.println(array[count]);
        count++;
    }
  2. Uma maneira melhor de usar um para cada loop, neste método, um programador não precisa se preocupar com o número de elementos na matriz.

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

De acordo com o seu código:

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

Se você verificar System.out.print (name.length);

você receberá 3;

isso significa que o comprimento do seu nome é 3

seu loop está sendo executado de 0 a 3, que deve estar executando "0 a 2" ou "1 a 3"

Responda

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

Cada item de uma matriz é chamado de elemento e cada elemento é acessado por seu índice numérico. Conforme mostrado na ilustração anterior, a numeração começa com 0 . O nono elemento, por exemplo, seria, portanto, acessado no índice 8.

IndexOutOfBoundsException é lançado para indicar que um índice de algum tipo (como uma matriz, uma string ou um vetor) está fora do intervalo.

Qualquer matriz X pode ser acessada de [0 a (X.length - 1)]

ZiadM
fonte
1

Vejo todas as respostas aqui explicando como trabalhar com matrizes e como evitar exceções fora do limite dos índices. Pessoalmente, evito matrizes a todo custo. Eu uso as classes Collections, que evitam toda a bobagem de ter que lidar inteiramente com os índices de array. As construções de loop funcionam lindamente com coleções que suportam código mais fácil de escrever, entender e manter.

John Czukkermann
fonte
1

Se você usar o comprimento de uma matriz para controlar a iteração de um loop for , lembre-se sempre de que o índice do primeiro item em uma matriz é 0 . Portanto, o índice do último elemento em uma matriz é um a menos que o comprimento da matriz.

Sachithra Dilshan
fonte
0

ArrayIndexOutOfBoundsException O próprio nome explica que, se você está tentando acessar o valor no índice que está fora do escopo do tamanho da matriz, ocorre esse tipo de exceção.

No seu caso, você pode apenas remover o sinal de igual do seu loop for.

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

A melhor opção é iterar uma matriz:

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

Esse erro ocorre nos tempos de sobreposição do loop de execuções. Vamos considerar um exemplo simples 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]+"  ");
    }
}

Inicialmente, eu inicializei uma matriz como 'numberArray'. então, alguns elementos da matriz são impressos usando o loop for. Quando o loop estiver executando o tempo 'i', imprima o elemento (numberArray [i + 1] .. (quando o valor i for 1, o elemento numberArray [i + 1] será impresso.) .. Suponha que, quando i = (numberArray. length-2), o último elemento da matriz é impresso. Quando o valor 'i' for (numberArray.length-1), não haverá valor para a impressão. Nesse ponto, ocorrerá 'ArrayIndexOutOfBoundsException'. Espero que você possa obter idea.thank você!

GT_hash
fonte
0

Você pode usar o Opcional no estilo funcional para evitar NullPointerExceptione 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);
}

Resultado:

AAA
NO_DATA
CCC
NO_DATA
Andrey Lavrukhin
fonte
-4

Não foi possível iterar ou armazenar mais dados que o comprimento da sua matriz. Nesse caso, você poderia fazer assim:

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

Ou isto:

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