Java.lang.ArrayIndexOutOfBoundsException neden olur ve nasıl önlerim?


299

Nedir ArrayIndexOutOfBoundsException geliyor ve ondan nasıl kurtulurum?

Kural dışı durumu tetikleyen bir kod örneği:

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

1
Son soruya referansla, kod yardımcı olacaktır. Diziye bilinen bir dizinle mi erişiyorsunuz, yoksa hata oluştuğunda dizinin nasıl hesaplandığını anlamak için hata ayıklamaya başlamanız mı gerekiyor?
justkt

43
Değiştir i <= name.lengthile i < name.length- ya da daha iyi bir döngü gelişmiş yazın. ( for (String aName : name) { ... })
Jean Hominal

1
bu, var olmayan bir dizi elemanını almak istediğiniz anlamına gelir, 'i <= name.length', eleman uzunluğu + 1'i almak istediğiniz anlamına gelir - mevcut değil.
gbk


Yanıtlar:


297

İlk çağrı limanınız, makul olarak açık bir şekilde açıklayan belgeler olmalıdır :

Geçersiz diziyle bir diziye erişildiğini göstermek için atılır. Dizin, negatif veya dizinin boyutuna eşit veya daha büyük.

Yani mesela:

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

Nasıl önleneceğine gelince ... hımm, bunu yapma. Dizi dizinlerinize dikkat edin.

İnsanların bazen karşılaştığı bir sorun, dizilerin 1 dizinli olduğunu düşünmektir.

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

Bu, ilk öğeyi (dizin 0) kaçırır ve dizin 5 olduğunda bir istisna atar. Buradaki geçerli dizinler 0-4'ü içerir. forBurada doğru, deyimsel ifade şöyle olacaktır:

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

(Bu , elbette dizine ihtiyacınız olduğunu varsayar . Bunun yerine gelişmiş for döngüsünü kullanabiliyorsanız bunu yapın.)


1
Java'da keyfi bir şekle sahip olabilecek çok boyutlu diziler için, iç içe döngülerin ilgili alt dizi uzunluğunu kontrol etmesi gerektiğini ekliyorum 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];
}

Ayrıca bakınız:


Güncelleme : kod snippet'inize göre,

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

Dizin, dizinin uzunluğunu içerir. Bu sınırların dışında. Sen değiştirmeniz gerekiyor <=tarafından <.

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

22

Bu mükemmel makaleden: Döngü için ArrayIndexOutOfBoundsException

Kısaca anlatmak için:

Son yinelemesinde

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

iname.lengthdizi endeksleri sıfır temelli olduğu için geçersiz bir dizine eşittir .

Kodunuz okunmalı

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

17

Bu, sınırlar arasında olmadığı için geçerli olmayan bir dizinin dizinine erişmeye çalıştığınız anlamına gelir.

Örneğin, bu üst sınır 4 ile ilkel bir tamsayı dizisi başlatacaktır.

int intArray[] = new int[5];

Programcılar sıfırdan sayılır. Yani bu, örneğin ArrayIndexOutOfBoundsException, üst sınır 5 değil 4'tür.

intArray[5];

4
Sınırlar aralık içindeki sınırlardır. örneğin; 0-5
John Giotta

11

Bir dizi dizini sınırların dışında istisnadan kaçınmak için, nerede ve ne zaman yapabildiklerinde , gelişmişfor ifadesi kullanılmalıdır.

Birincil motivasyon (ve kullanım örneği) yinelediğiniz ve karmaşık yineleme adımlarına ihtiyaç duymadığınız zamandır. Sen olur değil bir geliştirilmekte- kullanabilecektirfor bir dizideki geriye doğru taşımak veya yalnızca yinelerler her elemana için.

Bunu yaparken yinelenecek öğelerin tükenmemesi garanti edilir ve [düzeltilmiş] örneğiniz kolayca dönüştürülür.

Aşağıdaki kod:

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

... buna eşdeğerdir:

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

11

Sebebi nedir ArrayIndexOutOfBoundsException?

Bir değişkeni bir değer yerleştirebileceğiniz bir "kutu" olarak düşünüyorsanız, dizi birbirinin yanında yer alan bir dizi kutucuktur, burada kutu sayısı sonlu ve açık bir tamsayıdır.

Bunun gibi bir dizi oluşturma:

final int[] myArray = new int[5]

her biri bir int. Kutuların her biri bir dizin, kutu serisindeki bir konuma sahiptir. Bu dizin 0 ile başlar ve N-1 ile biter, burada N dizinin büyüklüğüdür (kutu sayısı).

Bu kutu serisindeki değerlerden birini almak için, aşağıdaki gibi dizininden başvurabilirsiniz:

myArray[3]

Bu size serideki 4. kutunun değerini verecektir (ilk kutunun dizini 0 olduğundan).

Bunun ArrayIndexOutOfBoundsExceptionnedeni, var olmayan bir "kutuyu" kurtarmaya çalışmaktır, son "kutu" dizininden daha yüksek veya negatif olan bir dizin iletmektir.

Çalışan örneğimde, bu kod parçacıkları böyle bir istisna oluşturur:

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

Nasıl önlenir ArrayIndexOutOfBoundsException

Önlemek ArrayIndexOutOfBoundsExceptioniçin dikkate alınması gereken bazı önemli noktalar vardır:

Döngü

Bir dizi arasında döngü yaparken, her zaman almakta olduğunuz dizinin dizinin uzunluğundan (kutu sayısından) kesinlikle daha küçük olduğundan emin olun. Örneğin:

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

Dikkat edin <, =orada asla karıştırmayın ..

Bunun gibi bir şey yapmaya cazip gelmek isteyebilirsiniz:

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

Sadece yapma. Yukarıdakine sadık kalın (endeksi kullanmanız gerekiyorsa) ve bu size çok fazla acı kazandıracaktır.

Mümkünse, foreach kullanın:

for (int value : myArray) {

Bu şekilde indeksleri düşünmek zorunda kalmayacaksınız.

Döngü yaparken, ne yaparsanız yapın, ASLA döngü yineleyicinin değerini değiştirmeyin (burada:) i. Bunun değer değiştirmesi gereken tek yer, döngüyü devam ettirmektir. Aksi takdirde sadece istisna riski vardır ve çoğu durumda gerekli değildir.

Alma / güncelleme

Dizinin isteğe bağlı bir öğesini alırken, dizinin uzunluğuna göre her zaman geçerli bir dizin olup olmadığını kontrol edin:

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

Kodunuzda, 0 dizininden dize dizisinin uzunluğuna kadar öğelere eriştiniz. name.lengthdize nesneleri dizinizdeki dize nesnelerinin sayısını verir, örneğin 3, ancak name[2]dizine 0 dizininden, name.length - 1elde ettiğiniz yere erişilebildiğinden, yalnızca dizin 2'ye kadar erişebilirsiniz.name.length nesne sayısını .

Bir fordöngü kullanırken bile dizin sıfır ile başladınız ve ile bitmelisiniz name.length - 1. A [n] dizisinde [0] 'dan [n-1]' e erişebilirsiniz.

Örneğin:

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

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

Senin durumunda:

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

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

5

Verilen diziniz için dizinin uzunluğu 3'tür (yani, name.length = 3). Ancak, dizin 0'dan başlayarak öğeyi depoladığından, maksimum dizin 2'ye sahiptir.

Bu nedenle, 'ArrayIndexOutOfBoundsException'ı önlemek için ' i ** <= name.length ' yerine ' i <** name.length 'yazmalısınız.


3

Bu basit soru için çok fazla, ama sadece Java'da yeni başlayanlar için bile dizilerde dizin oluşturmayla ilgili tüm karışıklıkları önleyecek yeni bir özelliği vurgulamak istedim. Java-8 sizin için yineleme görevini soyutladı.

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

Avantajı nedir? Bir şey, İngilizce gibi okunabilirlik. İkincisi, hakkında endişelenmenize gerek yokArrayIndexOutOfBoundsException


3

Bir kısmı ArrayIndexOutOfBoundsExceptionyüzünden alıyorsun i<=name.length. name.lengthstring uzunluğunu döndürür nameerişmeye çalıştığınızda Dolayısıyla 3'tür name[3]bu yasadışı ve bir istisna atar.

Çözülmüş kod:

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

Java dili belirtiminde tanımlanmıştır :

public finalAlan lengthdizisi bileşenlerinin sayısını içerir. lengthpozitif veya sıfır olabilir.


3

Dizi dizini sınırların dışında istisna

Eclipse'e atıldığında bu tür bir istisna böyle görünür. Kırmızı renkteki sayı erişmeye çalıştığınız dizini belirtir. Yani kod şöyle görünecektir:

myArray[5]

Bu dizide bulunmayan bir dizine erişmeye çalıştığınızda hata atılır. Bir dizinin uzunluğu 3 ise,

int[] intArray = new int[3];

geçerli tek dizinler:

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

Bir dizinin uzunluğu 1 ise,

int[] intArray = new int[1];

geçerli tek dizin:

intArray[0]

Dizinin uzunluğuna eşit veya ondan daha büyük herhangi bir tamsayı sınırların dışında.

0'dan küçük herhangi bir tam sayı sınır dışı;

Not: Dizileri daha iyi anlamak ve bazı pratik alıştırmalar yapmak istiyorsanız, burada bir video var: Java'daki dizilerle ilgili eğitim


3

Çok boyutlu diziler için, lengthdoğru boyutun özelliğine eriştiğinizden emin olmak zor olabilir . Örneğin, aşağıdaki kodu ele alalım:

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

Her boyutun farklı bir uzunluğu vardır, bu nedenle ince hata, orta ve iç döngülerin lengthaynı boyutun özelliğini kullanmasıdır (çünkü a[i].lengthaynıdır a[j].length).

Bunun yerine, iç döngü a[i][j].length(veya a[0][0].lengthbasitlik için) kullanmalıdır.


Eklenen bir kod örneği i koşulunu (çok boyutlu diziler) değiştirdiğinizde neden döngü değil çalışır? çünkü bu soru ArrayIndexOutOfBoundsException ile ilgili herhangi bir soru için bir dupe hedefi olarak kullanılır.
Kertenkele Bill

2

Görünüşe göre gizemli ArrayIndexOutOfBoundsExceptions için gördüğüm en yaygın durum, yani görünüşe göre kendi dizi işleme kodunuzun neden olmadığı, SimpleDateFormat'ın eşzamanlı kullanımıdır. Özellikle bir sunucu uygulamasında veya denetleyicide:

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

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

İki iş parçacığı SimplateDateFormat.parse () yöntemini birlikte girerse, büyük olasılıkla bir ArrayIndexOutOfBoundsException görürsünüz. SimpleDateFormat için javadoc sınıfının senkronizasyon bölümüne dikkat edin .

Kodunuzda, bir sunucu uygulaması ya da denetleyici gibi eşzamanlı olarak SimpleDateFormat gibi iş parçacığı güvensiz sınıflarına erişen bir yer olmadığından emin olun. Sunucu uygulamalarınızın ve denetleyicilerinizin tüm örnek değişkenlerini olası şüpheli olup olmadığını denetleyin.


2

Bu istisna her geldiğinde ArrayIndexOutOfBoundsException, sınırlarının dışında olan veya sıraya göre terimlerle başlattığınızdan daha fazlasını talep ettiğiniz bir dizi dizini kullanmaya çalıştığınız anlamına gelir.

Bunu önlemek için her zaman dizide bulunmayan bir dizin istemediğinizden emin olun, yani dizi uzunluğu 10 ise dizininiz 0 ile 9 arasında olmalıdır


2

ArrayIndexOutOfBounds, bir dizideki ayrılmamış bir konumu dizine eklemeye çalıştığınız anlamına gelir.

Bu durumda:

String[] name = { "tom", "dick", "harry" };
for (int i = 0; i <= name.length; i++) {
    System.out.println(name[i]);
}
  • dizi 3 String nesnesiyle tanımlandığından name.length 3'tür.
  • Bir dizinin içeriğine erişilirken, konum 0'dan başlar. 3 öğe olduğundan, ad [0] = "tom", ad [1] = "dick" ve ad [2] = "harry anlamına gelir.
  • Ne zaman döngü, çünkü ben , sen kullanılamaz erişim adıyla [3] çalıştığınız name.length için eşit veya daha az olabilir.

Bunu aşmak için ...

  • For döngüsü içinde i <name.length komutunu yapabilirsiniz. Bu, [3] adına döngüyü önler ve bunun yerine [2] adında durur

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

  • Her döngü için a kullanın

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

  • List.forEach (Tüketici eylemi) kullanın (Java8 gerektirir)

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

  • Diziyi akışa dönüştür - dizinize ek 'işlemler' gerçekleştirmek için iyi bir seçenektir, örneğin filtre, metni dönüştürme, bir haritaya dönüştürme vb. (Java8 gerektirir)

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


1

ArrayIndexOutOfBoundsException, dizinin var olmayan veya dizinin dışından dizinin bir dizinine erişmeye çalıştığınız anlamına gelir. Dizi dizinleri 0'dan başlar ve uzunluk - 1'de biter .

Senin durumunda

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

ArrayIndexOutOfBoundsExceptionvarolmayan name.length dizinli öğeye erişmeye çalıştığınızda oluşur (dizi dizini -1 ile biter). sadece <= yerine <koymak bu sorunu çözecektir.

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

1

Herhangi bir uzunluk n dizisi için, dizinin elemanları 0 ila n-1 arasında bir dizine sahip olacaktır.

Programınız dizi dizini n-1'den büyük olan herhangi bir öğeye (veya belleğe) erişmeye çalışıyorsa, Java ArrayIndexOutOfBoundsException özel durumunu atacaktır.

İşte bir programda kullanabileceğimiz iki çözüm

  1. Bakım sayısı:

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

    Veya başka bir döngü ifadesi gibi

    int count = 0;
    while(count < array.length) {
        System.out.println(array[count]);
        count++;
    }
  2. Her döngü için a ile daha iyi bir yol, bu yöntemde bir programcının dizideki elemanların sayısı hakkında endişelenmesine gerek yoktur.

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

1

Kodunuza göre:

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

System.out.print (name.length) öğesini işaretlerseniz;

3 alacaksınız;

yani isminizin uzunluğu 3

döngünüz 0 ile 3 arasında çalışıyor. Bu değer "0 ile 2" veya "1 ile 3" arasında olmalıdır

Cevap

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

1

Bir dizideki her öğeye öğe denir ve her öğeye kendi sayısal diziniyle erişilir. Önceki şekilde gösterildiği gibi, numaralandırma 0 ile başlar . Bu nedenle, 9. elemente, dizin 8'den erişilecektir.

IndexOutOfBoundsException, bir tür dizinin (bir dizi, bir dize veya bir vektör gibi) aralık dışında olduğunu belirtmek için atılır.

Herhangi bir X dizisine [0 - (X.length - 1)] arasında erişilebilir.


1

Burada dizilerle nasıl çalışılacağını ve dizin istisnalarının dışında dizinin nasıl önleneceğini açıklayan tüm yanıtları görüyorum. Şahsen dizilerden kaçınıyorum. Dizi indeksleri ile başa çıkmak zorunda kalmanın tüm sersemliklerini önleyen Collections sınıflarını kullanıyorum. Döngü yapıları, hem yazması, anlaması hem de bakımı daha kolay olan kodu destekleyen koleksiyonlarla güzel çalışır.


1

For döngüsünün yinelemesini denetlemek için bir dizinin uzunluğunu kullanırsanız, dizideki ilk öğenin dizininin 0 olduğunu unutmayın . Bu nedenle, bir dizideki son öğenin dizini, dizinin uzunluğundan bir daha azdır.


0

ArrayIndexOutOfBoundsException adının kendisi, dizinin Array boyutu kapsamı dışında kalan değere erişmeye çalıştığınızda bu tür bir istisna oluştuğunu açıklar.

Sizin durumunuzda, for döngüsünden eşittir işaretini kaldırabilirsiniz.

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

Daha iyi bir seçenek bir diziyi yinelemektir:

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

0

Bu hata, çalışır döngü overlimit sürelerinde oluşur. Bunun gibi basit bir örneği ele alalım,

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

İlk başta bir diziyi 'numberArray' olarak başlattım. daha sonra, bazı dizi elemanları for döngüsü kullanılarak yazdırılır. Döngü 'i' zamanını çalıştırırken, (numberArray [i + 1] öğesini yazdırın. (İ değeri 1 olduğunda, numberArray [i + 1] öğesi yazdırılır.) .. Varsayalım ki, i = (numberArray. uzunluk-2), dizinin son öğesi yazdırılır ... 'i' değeri (numberArray.length-1) olduğunda, yazdırma için değer yok ... Bu noktada 'ArrayIndexOutOfBoundsException' oluşur. fikir. teşekkür ederim!


0

Sen kaçınmak için işlevsel bir tarzda İsteğe bağlı kullanabilir NullPointerExceptionve 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);
}

Çıktı:

AAA
NO_DATA
CCC
NO_DATA

-4

Dizinizin uzunluğundan daha fazla veri yineleyemez veya depolayamazsınız. Bu durumda şöyle yapabilirsiniz:

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

Veya bu:

for (int i = 0; i < name.length; i++) {
    // ...
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.