java.lang.ArrayIndexOutOfBoundsException의 원인은 무엇이며 어떻게 방지합니까?


298

무엇을 하는가 ArrayIndexOutOfBoundsException 의미하며 어떻게 제거합니까?

다음은 예외를 트리거하는 코드 샘플입니다.

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

1
마지막 질문과 관련하여 코드가 도움이 될 것입니다. 알려진 인덱스가있는 어레이에 액세스하고 있거나 오류가 발생할 때 인덱스가 계산되는 방법을 파악하기 위해 디버깅을 시작해야합니까?
justkt

43
교체 i <= name.lengthi < name.length- 또는 더 나은, 루프에 대한 강화 된 물품. ( for (String aName : name) { ... })
Jean Hominal

1
즉, 존재하지 않는 배열의 요소를 가져 오려면 'i <= name.length'는 요소 길이 +1-존재하지 않음을 의미합니다.
gbk


답변:


296

첫 번째 포트는 합리적으로 명확하게 설명 하는 문서 여야합니다 .

잘못된 인덱스로 배열에 액세스했음을 나타냅니다. 인덱스가 음수이거나 배열 크기보다 크거나 같습니다.

예를 들어 :

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

그것을 피하는 방법에 관해서는 ... 음, 그렇게하지 마십시오. 배열 인덱스에주의하십시오.

사람들이 때때로 겪는 한 가지 문제는 배열이 1- 인덱싱된다는 생각입니다

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

첫 번째 요소 (인덱스 0)가 누락되고 인덱스가 5 일 때 예외가 발생합니다. 유효한 인덱스는 0-4입니다. 올바른 관용구 for문은 다음과 같습니다.

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

( 물론 인덱스 가 필요 하다고 가정합니다 . 대신 고급 for 루프를 사용할 수 있다면 그렇게하십시오.)


1
Java에서 임의의 모양을 가질 수있는 다차원 배열의 경우 중첩 루프가 관련 하위 배열 길이를 확인해야한다고 덧붙 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];
}

또한보십시오:


업데이트 : 코드 스 니펫에 따라

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

인덱스는 배열의 길이를 포함합니다. 이 범위를 벗어났습니다. 당신은 교체 할 필요 <=<.

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

22

이 훌륭한 기사에서 : for 루프의 ArrayIndexOutOfBoundsException

간단히 말해 :

마지막 반복에서

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

i 같을 것이다 name.length 배열 인덱스이기 때문에, 부정한 인덱스 인 제로 기반.

코드를 읽어야합니다

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

17

그것은 경계 사이에 있지 않으므로 유효하지 않은 배열의 인덱스에 액세스하려고한다는 것을 의미합니다.

예를 들어 상한 4로 기본 정수 배열을 초기화합니다.

int intArray[] = new int[5];

프로그래머는 0부터 계산합니다. 따라서 예를 들어 ArrayIndexOutOfBoundsException상한이 4이고 5가 아니기 때문에 a를 던질 것 입니다.

intArray[5];

4
범위는 범위 내 한계입니다. 즉; 0-5
John Giotta

11

배열 인덱스 범위를 벗어난 예외를 방지하려면 Enhancedfor 문을 언제 어디서나 사용할 수 있어야합니다 .

주요 동기 부여 (및 사용 사례)는 반복 할 때 복잡한 반복 단계가 필요하지 않은 경우입니다. 당신은 할 수 없습니다 이 고급을 사용할 수for 하여 배열에서 뒤로 이동하거나 다른 모든 요소에서만 반복 .

이 작업을 수행 할 때 반복 할 요소가 부족하지 않도록 보장되며 [수정 된] 예제가 쉽게 변환됩니다.

아래 코드 :

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

... 이와 같습니다 :

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

11

원인은 무엇입니까 ArrayIndexOutOfBoundsException?

변수를 값을 배치 할 수있는 "상자"로 생각하면 배열은 서로 옆에 배치 된 일련의 상자이며 상자의 수는 유한하고 명시적인 정수입니다.

다음과 같은 배열 만들기 :

final int[] myArray = new int[5]

각각 5 개의 상자가있는 행을 만듭니다 int. 각 상자에는 일련의 상자에 위치하는 색인이 있습니다. 이 인덱스는 0에서 시작하여 N-1에서 끝납니다. 여기서 N은 배열의 크기 (상자 수)입니다.

이 일련의 상자에서 값 중 하나를 검색하려면 다음과 같이 색인을 통해 참조하십시오.

myArray[3]

이것은 첫 번째 상자에 색인 0이 있기 때문에 시리즈의 네 번째 상자 값을 제공합니다.

ArrayIndexOutOfBoundsException마지막으로 "상자", 또는 음의 인덱스보다 높은 인덱스를 전달하여, 존재하지 않는 "상자"를 가져 오지 노력에 의해 발생합니다.

실행중인 예제 에서이 코드 스 니펫은 이러한 예외를 생성합니다.

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

피하는 법 ArrayIndexOutOfBoundsException

를 방지하기 위해 ArrayIndexOutOfBoundsException고려해야 할 몇 가지 핵심 사항이 있습니다.

루핑

배열을 반복 할 때 항상 검색하는 색인이 배열의 길이 (상자 수)보다 엄격하게 작아야합니다. 예를 들어 :

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

<혼용하지 마십시오 =.

다음과 같은 일을하고 싶을 수도 있습니다.

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

하지마 위의 것을 고수하고 (색인을 사용해야하는 경우) 많은 고통을 덜어줍니다.

가능하면 다음을 사용하십시오.

for (int value : myArray) {

이런 식으로 인덱스에 대해 전혀 생각할 필요가 없습니다.

루핑 할 때 어떤 작업을 수행하더라도 루프 반복기의 값을 변경하지 마십시오 (여기 :) i. 이 값을 변경해야하는 유일한 장소는 루프를 계속 진행하는 것입니다. 달리 변경하면 예외가 발생할 수 있으며 대부분의 경우 필요하지 않습니다.

검색 / 업데이트

배열의 임의의 요소를 검색 할 때는 항상 배열의 길이에 대한 유효한 색인인지 확인하십시오.

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

6

코드에서 인덱스 0에서 문자열 배열의 길이에 이르는 요소에 액세스했습니다. name.length는 문자열 객체 배열 즉, 3의 문자열 객체 수를 제공하지만 name[2]인덱스 0에서 객체 수 name.length - 1를 얻는 위치 까지 배열에 액세스 할 수 있기 때문에 최대 인덱스 2에만 액세스 할 수 있습니다 name.length.

for루프 를 사용하는 동안에도 인덱스 0으로 시작했으며로 끝나야합니다 name.length - 1. 배열 a [n]에서는 형식 a [0]에서 a [n-1]에 액세스 할 수 있습니다.

예를 들면 다음과 같습니다.

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

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

귀하의 경우 :

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

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

5

주어진 배열의 경우 배열의 길이는 3입니다 (예 : name.length = 3). 그러나 인덱스 0에서 시작하는 요소를 저장하므로 최대 인덱스 2가 있습니다.

따라서 'i ** <= name.length' 대신 'ArrayIndexOutOfBoundsException'을 피하기 위해 ' i <** name.length'를 작성해야합니다 .


3

이 간단한 질문에 대해서는 너무 많았지 만 초보자조차도 배열의 색인 작성과 관련된 모든 혼란을 피할 수있는 Java의 새로운 기능을 강조하고 싶었습니다. Java-8은 반복 작업을 추상화했습니다.

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

장점은 무엇입니까? 글쎄, 한 가지는 영어와 같은 가독성입니다. 둘째, 걱정할 필요가 없습니다.ArrayIndexOutOfBoundsException


3

당신은 부분 ArrayIndexOutOfBoundsException으로 인해 지고있다 i<=name.length. name.length문자열 길이를 반환합니다. name3입니다. 따라서 액세스하려고하면 name[3]불법이며 예외가 발생합니다.

해결 된 코드 :

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

Java 언어 사양에 정의되어 있습니다 .

public final필드 length배열의 요소의 수를 포함. length양수 또는 0 일 수 있습니다.


3

범위를 벗어난 배열 인덱스 예외

이것이 Eclipse에서 발생했을 때 이러한 유형의 예외가 나타나는 방식입니다. 빨간색 숫자는 액세스하려는 색인을 나타냅니다. 따라서 코드는 다음과 같습니다.

myArray[5]

해당 배열에 존재하지 않는 인덱스에 액세스하려고하면 오류가 발생합니다. 배열의 길이가 3이면

int[] intArray = new int[3];

유효한 인덱스는 다음과 같습니다.

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

배열의 길이가 1이면

int[] intArray = new int[1];

유효한 인덱스는 다음과 같습니다.

intArray[0]

배열의 길이와 같거나 그보다 큰 정수는 범위를 벗어납니다.

0보다 작은 정수는 범위를 벗어납니다.

추신 : 배열에 대해 더 잘 이해하고 실용적인 연습을 수행하려면 여기 비디오가 있습니다 : Java 배열에 대한 자습서


3

다차원 배열 length의 경우 올바른 차원 의 속성에 액세스하는 것이 까다로울 수 있습니다 . 예를 들어 다음 코드를 사용하십시오.

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

미묘한 버그가 중간 및 내부 루프를 사용하는 것이다 각각의 사이즈는 서로 다른 길이를 갖는다 length(때문에 동일한 차원의 속성 a[i].length과 동일하다 a[j].length).

대신 내부 루프는 a[i][j].length (또는 a[0][0].length단순화를 위해) .


조건 (다차원 배열)을 변경할 때 왜 for 루프가 작동하지 않습니까? 의 코드 예제를 추가했습니다 . 이 질문은 ArrayIndexOutOfBoundsException을 다루는 모든 질문에 대한 중복 대상으로 사용되기 때문입니다.
Bill the Lizard

2

내가보기에 신비한 ArrayIndexOutOfBoundsExceptions에 대해 본 가장 일반적인 경우는, 즉 자신의 배열 처리 코드로 인해 발생하지 않는 것 같습니다. SimpleDateFormat의 동시 사용입니다. 특히 서블릿 또는 컨트롤러에서 :

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

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

두 개의 스레드가 SimplateDateFormat.parse () 메서드를 함께 입력하면 ArrayIndexOutOfBoundsException이 발생할 수 있습니다. SimpleDateFormat에 대한 javadoc 클래스 의 동기화 섹션을 참고하십시오 .

코드에 서블릿이나 컨트롤러와 같이 동시 방식으로 SimpleDateFormat과 같은 스레드 안전하지 않은 클래스에 액세스하는 장소가 없는지 확인하십시오. 서블릿 및 컨트롤러의 모든 인스턴스 변수에서 의심이 있는지 확인하십시오.


2

이 예외가 발생할 때마다 ArrayIndexOutOfBoundsException은 배열의 범위를 벗어나거나 초기화 한 것보다 더 많이 요청하는 일반인의 배열 색인을 사용하려고 함을 의미합니다.

이를 방지하려면 항상 배열에없는 색인을 요청하지 않아야합니다. 즉 배열 길이가 10 인 경우 색인의 범위는 0에서 9 사이 여야합니다.


2

ArrayIndexOutOfBounds는 할당되지 않은 배열 내 위치를 색인하려고 함을 의미합니다.

이 경우 :

String[] name = { "tom", "dick", "harry" };
for (int i = 0; i <= name.length; i++) {
    System.out.println(name[i]);
}
  • 배열이 3 개의 String 객체로 정의되었으므로 name.length는 3입니다.
  • 배열의 내용에 액세스 할 때 위치는 0부터 시작합니다. 3 개의 항목이 있으므로 name [0] = "tom", name [1] = "dick"및 name [2] = "harry
  • 루프 할 때 i 가 name.length보다 작거나 같을 수 없으므로 사용할 수없는 name [3]에 액세스하려고합니다.

이 문제를 해결하려면 ...

  • for 루프에서 i <name.length를 수행 할 수 있습니다. 이렇게하면 name [3]으로의 루핑이 방지되고 대신 name [2]에서 중지됩니다.

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

  • 각 루프에 대해

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

  • list.forEach (소비자 조치) 사용 (Java8 필요)

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

  • 배열을 스트림으로 변환-배열에 대한 추가 '작업'을 수행하려는 경우 좋은 옵션입니다 (예 : 필터, 텍스트 변환, 맵으로 변환 등) (Java8 필요)

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


1

ArrayIndexOutOfBoundsException존재하지 않거나이 배열의 범위를 벗어난 배열의 인덱스에 액세스하려고 함을 의미합니다. 배열 인덱스는 0 에서 시작 하여 길이-1 에서 끝납니다 .

당신의 경우

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

ArrayIndexOutOfBoundsException존재하지 않는 name.length 인덱싱 된 요소에 액세스하려고 할 때 발생합니다 (배열 인덱스는 길이 -1로 끝남). <=를 <로 바꾸면이 문제가 해결됩니다.

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

1

길이가 n 인 배열의 경우 배열의 요소는 0에서 n-1 사이의 인덱스를 갖습니다.

프로그램이 n-1보다 큰 배열 색인을 가진 요소 또는 메모리에 액세스하려고하면 Java는 ArrayIndexOutOfBoundsException을 발생시킵니다.

다음은 프로그램에서 사용할 수있는 두 가지 솔루션입니다.

  1. 카운트 유지 :

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

    또는 같은 다른 반복문

    int count = 0;
    while(count < array.length) {
        System.out.println(array[count]);
        count++;
    }
  2. 더 좋은 방법은 각 루프마다 for를 사용하는 것입니다.이 방법에서는 프로그래머가 배열의 요소 수를 신경 쓸 필요가 없습니다.

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

1

귀하의 코드에 따르면 :

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

System.out.print (name.length);를 확인하면

당신은 3을 얻을 것이다;

그것은 당신의 이름 길이가 3이라는 것을 의미합니다

루프가 0에서 3으로 실행되고 "0에서 2"또는 "1에서 3"으로 실행되어야합니다.

대답

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

1

배열의 각 항목을 요소라고하며 각 요소는 숫자 인덱스로 액세스합니다. 앞의 그림에서와 같이 번호 매기기는 0으로 시작합니다. . 예를 들어 9 번째 요소는 인덱스 8에서 액세스됩니다.

IndexOutOfBoundsException은 배열, 문자열 또는 벡터와 같은 일종의 인덱스가 범위를 벗어 났음을 나타 내기 위해 발생합니다.

모든 배열 X는 [0에서 (X.length-1)]까지 액세스 할 수 있습니다.


1

배열로 작업하는 방법과 범위를 벗어난 색인을 피하는 방법을 설명하는 모든 대답이 있습니다. 나는 개인적으로 모든 비용으로 배열을 피합니다. 나는 Collections 클래스를 사용하는데, 이는 배열 인덱스를 완전히 다루어야하는 모든 어리 석음을 피한다. 루핑 구문은 작성, 이해 및 유지 관리가 더 쉬운 코드를 지원하는 컬렉션에서 아름답게 작동합니다.


1

배열의 길이를 사용하여 for 루프의 반복을 제어하는 ​​경우 배열의 첫 번째 항목의 색인이 항상 0 임을 기억하십시오 . 따라서 배열에서 마지막 요소의 인덱스는 배열의 길이보다 1이 적습니다.


0

ArrayIndexOutOfBoundsException 이름 자체는 배열 크기의 범위를 벗어난 색인의 값에 액세스하려고하면 그러한 종류의 예외가 발생한다고 설명합니다.

귀하의 경우 for 루프에서 등호를 제거하면됩니다.

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

더 나은 옵션은 배열을 반복하는 것입니다.

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

0

이 오류는 루프 초과 제한 시간이 실행될 때 발생합니다.

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

처음에는 배열을 'numberArray'로 초기화했습니다. 그런 다음 for 배열을 사용하여 일부 배열 요소가 인쇄됩니다. loop가 'i'time을 실행 중이면 (numberArray [i + 1] 요소를 인쇄하십시오. (i 값이 1이면 numberArray [i + 1] 요소가 인쇄됩니다.). i = (numberArray 인 경우 제공하십시오. 길이-2), 배열의 마지막 요소가 인쇄됩니다 .'i '값이 (numberArray.length-1)로 이동하면 인쇄 값이 없습니다. 그 시점에서'ArrayIndexOutOfBoundsException '이 발생합니다. idea.thank 감사합니다!


0

기능적 스타일에서 옵션을 사용 NullPointerException하여 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);
}

산출:

AAA
NO_DATA
CCC
NO_DATA

-4

배열 길이보다 더 많은 데이터를 반복하거나 저장할 수 없습니다. 이 경우 다음과 같이 할 수 있습니다.

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

아니면 이거:

for (int i = 0; i < name.length; i++) {
    // ...
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.