Apa yang menyebabkan java.lang.ArrayIndexOutOfBoundsException dan bagaimana cara mencegahnya?

298

Apa ArrayIndexOutOfBoundsExceptionmaksudnya dan bagaimana cara menghilangkannya?

Berikut adalah contoh kode yang memicu pengecualian:

String[] names = { "tom", "bob", "harry" };
for (int i = 0; i <= names.length; i++) {
    System.out.println(names[i]);
}
Harun
sumber
1
Mengacu pada pertanyaan terakhir, kode akan sangat membantu. Apakah Anda mengakses array dengan indeks yang diketahui, atau apakah Anda harus mulai debugging untuk mengetahui bagaimana indeks dihitung ketika kesalahan terjadi?
justkt
43
Ganti i <= name.lengthdengan i < name.length- atau lebih baik, tuliskan pengulangan untuk loop. ( for (String aName : name) { ... })
Jean Hominal
1
itu berarti, bahwa Anda ingin mendapatkan elemen array yang tidak ada, 'i <= name.length' berarti Anda ingin mendapatkan panjang elemen +1 - itu tidak ada.
gbk

Jawaban:

296

Pelabuhan panggilan pertama Anda harus berupa dokumentasi yang menjelaskannya dengan cukup jelas:

Dilemparkan untuk menunjukkan bahwa array telah diakses dengan indeks ilegal. Indeksnya negatif atau lebih besar dari atau sama dengan ukuran array.

Jadi misalnya:

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

Adapun cara menghindarinya ... um, jangan lakukan itu. Hati-hati dengan indeks array Anda.

Satu masalah yang terkadang ditemui orang adalah berpikir bahwa array adalah 1-diindeks, misalnya

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

Itu akan kehilangan elemen pertama (indeks 0) dan melemparkan pengecualian ketika indeks 5. Indeks yang valid di sini adalah 0-4 inklusif. forPernyataan idiomatik yang benar di sini adalah:

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

(Itu dengan asumsi Anda memerlukan indeks, tentu saja. Jika Anda dapat menggunakan yang ditingkatkan untuk loop, lakukanlah.)

Jon Skeet
sumber
1
Saya akan menambahkan bahwa untuk array multidimensi yang mungkin memiliki bentuk sewenang-wenang di Jawa, loop bersarang harus memeriksa panjang subarray yang relevan: 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];
}

Lihat juga:


Perbarui : sesuai cuplikan kode Anda,

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

Indeks ini termasuk panjang array. Ini di luar batas. Anda harus mengganti <=dengan <.

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

Dari artikel yang bagus ini: ArrayIndexOutOfBoundsException in for loop

Singkatnya:

Dalam iterasi terakhir

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

iakan sama dengan name.lengthyang merupakan indeks ilegal, karena indeks array berbasis nol.

Kode Anda harus dibaca

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

Ini berarti bahwa Anda mencoba mengakses indeks array yang tidak valid karena tidak berada di antara batas.

Misalnya ini akan menginisialisasi array integer primitif dengan batas atas 4.

int intArray[] = new int[5];

Programmer dihitung dari nol. Jadi ini misalnya akan melempar ArrayIndexOutOfBoundsExceptionkarena batas atas adalah 4 dan bukan 5.

intArray[5];
Oktavianus A. Damiean
sumber
4
Batas adalah batas dalam kisaran. yaitu; 0-5
John Giotta
11

Untuk menghindari pengecualian indeks array di luar batas, seseorang harus menggunakan pernyataan yang ditingkatkan difor mana dan kapan mereka bisa.

Motivasi utama (dan use case) adalah ketika Anda melakukan iterasi dan Anda tidak memerlukan langkah iterasi yang rumit. Anda tidak akan bisa menggunakan yang disempurnakan foruntuk bergerak mundur dalam array atau hanya mengulangi pada setiap elemen lainnya.

Anda dijamin tidak kehabisan elemen untuk beralih saat melakukan ini, dan contoh [yang diperbaiki] Anda mudah dikonversi.

Kode di bawah ini:

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

... sama dengan ini:

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

Apa yang menyebabkan ArrayIndexOutOfBoundsException?

Jika Anda menganggap variabel sebagai "kotak" di mana Anda dapat menempatkan nilai, maka array adalah serangkaian kotak yang ditempatkan di sebelah satu sama lain, di mana jumlah kotak adalah bilangan bulat terbatas dan eksplisit.

Membuat array seperti ini:

final int[] myArray = new int[5]

menciptakan deretan 5 kotak, masing-masing memegang sebuah int. Setiap kotak memiliki indeks, posisi dalam serangkaian kotak. Indeks ini dimulai pada 0, dan berakhir pada N-1, di mana N adalah ukuran array (jumlah kotak).

Untuk mengambil salah satu nilai dari seri kotak ini, Anda bisa merujuknya melalui indeksnya, seperti ini:

myArray[3]

Yang akan memberi Anda nilai kotak ke-4 dalam seri (karena kotak pertama memiliki indeks 0).

An ArrayIndexOutOfBoundsExceptiondisebabkan oleh mencoba untuk mengambil kembali "kotak" yang tidak ada, dengan melewati indeks yang lebih tinggi dari indeks "kotak" terakhir, atau negatif.

Dengan contoh saya yang sedang berjalan, cuplikan kode ini akan menghasilkan pengecualian seperti itu:

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

Bagaimana cara menghindarinya ArrayIndexOutOfBoundsException

Untuk mencegah ArrayIndexOutOfBoundsException, ada beberapa poin penting untuk dipertimbangkan:

Looping

Saat mengulang melalui array, selalu pastikan bahwa indeks yang Anda ambil benar-benar lebih kecil dari panjang array (jumlah kotak). Misalnya:

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

Perhatikan <, jangan pernah campur =di sana ..

Anda mungkin ingin tergoda untuk melakukan sesuatu seperti ini:

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

Hanya saja, jangan. Tetap pada yang di atas (jika Anda perlu menggunakan indeks) dan itu akan menghemat banyak rasa sakit.

Jika memungkinkan, gunakan foreach:

for (int value : myArray) {

Dengan cara ini Anda tidak perlu memikirkan indeks sama sekali.

Saat perulangan, apa pun yang Anda lakukan, JANGAN PERNAH mengubah nilai loop iterator (di sini:) i. Satu-satunya tempat ini harus mengubah nilai adalah untuk menjaga loop tetap berjalan. Mengubahnya dengan cara lain hanya berisiko mengambil pengecualian, dan dalam banyak kasus tidak perlu.

Pengambilan / pembaruan

Ketika mengambil elemen arbitrer dari array, selalu periksa bahwa itu adalah indeks yang valid terhadap panjang array:

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

Dalam kode Anda, Anda telah mengakses elemen dari indeks 0 hingga panjang array string. name.lengthmemberikan jumlah objek string dalam array Anda objek string yaitu 3, tetapi Anda hanya dapat mengakses hingga indeks 2 name[2], karena array dapat diakses dari indeks 0 ke name.length - 1tempat Anda mendapatkan name.lengthjumlah objek.

Bahkan saat menggunakan forloop Anda sudah mulai dengan indeks nol dan Anda harus mengakhiri dengan name.length - 1. Dalam array a [n] Anda dapat mengakses form [0] ke [n-1].

Sebagai contoh:

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

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

Dalam kasus Anda:

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

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

Untuk larik yang Anda berikan, panjang larik adalah 3 (yaitu name.length = 3). Tetapi karena ia menyimpan elemen mulai dari indeks 0, ia memiliki indeks max 2.

Jadi, alih-alih 'i ** <= name.length' Anda harus menulis 'i <** name.length' untuk menghindari 'ArrayIndexOutOfBoundsException'.

nikil
sumber
3

Begitu banyak untuk pertanyaan sederhana ini, tetapi saya hanya ingin menyoroti fitur baru di Jawa yang akan menghindari semua kebingungan seputar pengindeksan dalam array bahkan untuk pemula. Java-8 telah mengabstraksi tugas iterasi untuk Anda.

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

Apa untungnya? Nah, satu hal adalah keterbacaan seperti bahasa Inggris. Kedua, Anda tidak perlu khawatir tentangArrayIndexOutOfBoundsException

Satyendra Kumar
sumber
3

Anda mendapatkan ArrayIndexOutOfBoundsExceptionkarena i<=name.lengthsebagian. name.lengthmengembalikan panjang string name, yaitu 3. Karenanya ketika Anda mencoba mengakses name[3], itu ilegal dan melempar pengecualian.

Kode yang diselesaikan:

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

Ini didefinisikan dalam spesifikasi bahasa Java :

The public finallapangan length, yang berisi jumlah komponen dari array. lengthmungkin positif atau nol.

roottraveller
sumber
3

Indeks array di luar batas

Begitulah cara jenis pengecualian ini terlihat ketika dilemparkan ke Eclipse. Angka berwarna merah menandakan indeks yang Anda coba akses. Jadi kodenya akan terlihat seperti ini:

myArray[5]

Kesalahan terjadi ketika Anda mencoba mengakses indeks yang tidak ada dalam array itu. Jika sebuah array memiliki panjang 3,

int[] intArray = new int[3];

maka satu-satunya indeks yang valid adalah:

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

Jika sebuah array memiliki panjang 1,

int[] intArray = new int[1];

maka satu-satunya indeks yang valid adalah:

intArray[0]

Bilangan bulat apa pun yang sama dengan panjang array, atau lebih besar dari itu: di luar batas.

Bilangan bulat apa pun yang kurang dari 0: di luar batas;

PS: Jika Anda terlihat memiliki pemahaman yang lebih baik tentang array dan melakukan beberapa latihan praktis, ada video di sini: tutorial tentang array di Jawa

Johny
sumber
3

Untuk array multidimensi, mungkin sulit untuk memastikan Anda mengakses lengthproperti dari dimensi yang tepat. Ambil kode berikut sebagai contoh:

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

Setiap dimensi memiliki panjang yang berbeda, sehingga bug halus adalah bahwa loop tengah dan dalam menggunakan lengthproperti dari dimensi yang sama (karena a[i].lengthsama dengan a[j].length).

Sebagai gantinya, loop dalam harus menggunakan a[i][j].length(atau a[0][0].length, untuk kesederhanaan).

Bill the Lizard
sumber
Menambahkan contoh kode dari Mengapa loop saya tidak berfungsi ketika saya mengubah kondisinya (array multidimensi)? karena pertanyaan ini digunakan sebagai target dupe untuk setiap pertanyaan yang berhubungan dengan ArrayIndexOutOfBoundsException.
Bill the Lizard
2

Kasus paling umum yang pernah saya lihat untuk ArrayIndexOutOfBoundsExceptions yang tampaknya misterius, yaitu tampaknya tidak disebabkan oleh kode penanganan array Anda sendiri, adalah penggunaan bersamaan dari SimpleDateFormat. Khususnya dalam servlet atau controller:

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

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

Jika dua utas memasukkan metode SimplateDateFormat.parse () bersama-sama, Anda mungkin akan melihat ArrayIndexOutOfBoundsException. Perhatikan bagian sinkronisasi javadoc kelas untuk SimpleDateFormat .

Pastikan tidak ada tempat dalam kode Anda yang mengakses utas kelas yang tidak aman seperti SimpleDateFormat secara bersamaan seperti di servlet atau controller. Periksa semua variabel instan servlet dan pengontrol Anda untuk kemungkinan tersangka.

Kyri Sarantakos
sumber
2

ArrayIndexOutOfBoundsException setiap kali pengecualian ini datang itu berarti Anda mencoba menggunakan indeks array yang di luar batasnya atau dalam istilah orang awam Anda meminta lebih dari yang Anda inisialisasi.

Untuk mencegah hal ini selalu pastikan bahwa Anda tidak meminta indeks yang tidak ada dalam array yaitu jika panjang array adalah 10 maka indeks Anda harus berkisar antara 0 hingga 9

sgrpwr
sumber
2

ArrayIndexOutOfBounds berarti Anda mencoba mengindeks posisi dalam array yang tidak dialokasikan.

Pada kasus ini:

String[] name = { "tom", "dick", "harry" };
for (int i = 0; i <= name.length; i++) {
    System.out.println(name[i]);
}
  • name.length adalah 3 karena array telah didefinisikan dengan 3 objek String.
  • Saat mengakses konten array, posisi dimulai dari 0. Karena ada 3 item, itu berarti nama [0] = "tom", nama [1] = "kontol" dan nama [2] = "harry
  • Saat Anda mengulang, karena saya bisa kurang dari atau sama dengan name.length, Anda mencoba mengakses nama [3] yang tidak tersedia.

Untuk menyiasati ini ...

  • Di for for loop Anda, Anda bisa melakukan i <name.length. Ini akan mencegah perulangan ke nama [3] dan sebagai gantinya akan berhenti di nama [2]

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

  • Gunakan a untuk setiap loop

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

  • Gunakan list.forEach (Tindakan konsumen) (memerlukan Java8)

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

  • Konversi array ke streaming - ini adalah opsi yang baik jika Anda ingin melakukan 'operasi' tambahan untuk array Anda mis. Filter, mengubah teks, mengkonversi ke peta dll (memerlukan Java8)

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

martinywwan
sumber
1

ArrayIndexOutOfBoundsExceptionberarti bahwa Anda mencoba mengakses indeks array yang tidak ada atau di luar batas array ini. Indeks array mulai dari 0 dan berakhir panjang - 1 .

Dalam kasus Anda

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

ArrayIndexOutOfBoundsExceptionterjadi ketika Anda mencoba mengakses elemen diindeks name.length yang tidak ada (indeks array berakhir pada panjang -1). hanya mengganti <= dengan <akan menyelesaikan masalah ini.

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

Untuk setiap array dengan panjang n, elemen array akan memiliki indeks dari 0 hingga n-1.

Jika program Anda mencoba mengakses elemen (atau memori) apa pun yang memiliki indeks larik lebih besar dari n-1, maka Java akan membuang ArrayIndexOutOfBoundsException

Jadi, inilah dua solusi yang bisa kita gunakan dalam suatu program

  1. Mempertahankan hitungan:

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

    Atau pernyataan perulangan lainnya seperti

    int count = 0;
    while(count < array.length) {
        System.out.println(array[count]);
        count++;
    }
  2. Cara yang lebih baik digunakan dengan untuk setiap loop, dalam metode ini seorang programmer tidak perlu repot tentang jumlah elemen dalam array.

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

Menurut Kode Anda:

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

Jika Anda memeriksa System.out.print (name.length);

Anda akan mendapatkan 3;

itu berarti panjang nama Anda adalah 3

lingkaran Anda berjalan dari 0 hingga 3 yang seharusnya berjalan "0 hingga 2" atau "1 hingga 3"

Menjawab

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

Setiap item dalam array disebut elemen, dan setiap elemen diakses oleh indeks numeriknya. Seperti yang ditunjukkan pada ilustrasi sebelumnya, penomoran dimulai dengan 0 . Elemen ke-9, misalnya, karenanya akan diakses pada indeks 8.

IndexOutOfBoundsException dilemparkan untuk menunjukkan bahwa suatu indeks semacam (seperti untuk array, ke string, atau ke vektor) berada di luar jangkauan.

Setiap array X, dapat diakses dari [0 hingga (X.length - 1)]

ZiadM
sumber
1

Saya melihat semua jawaban di sini menjelaskan cara bekerja dengan array dan bagaimana cara untuk menghindari pengecualian indeks. Saya pribadi menghindari array di semua biaya. Saya menggunakan kelas Koleksi, yang menghindari semua kekonyolan karena harus berurusan dengan indeks array sepenuhnya. Konstruksi pengulangan berfungsi dengan baik dengan koleksi kode pendukung yang lebih mudah untuk ditulis, dipahami, dan dipelihara.

John Czukkermann
sumber
1

Jika Anda menggunakan panjang array untuk mengontrol iterasi loop for , selalu ingat bahwa indeks item pertama dalam array adalah 0 . Jadi indeks elemen terakhir dalam array adalah kurang dari panjang array.

Sachithra Dilshan
sumber
0

ArrayIndexOutOfBoundsException name itu sendiri menjelaskan bahwa Jika Anda mencoba mengakses nilai pada indeks yang berada di luar cakupan ukuran array maka pengecualian semacam itu terjadi.

Dalam kasus Anda, Anda bisa menghapus tanda sama dari for for loop Anda.

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

Opsi yang lebih baik adalah dengan mengulangi array:

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

Kesalahan ini terjadi saat menjalankan loop overlimit kali. Mari kita perhatikan contoh sederhana seperti ini,

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

Pada awalnya, saya telah menginisialisasi array sebagai 'numberArray'. kemudian, beberapa elemen array dicetak menggunakan for loop. Ketika loop menjalankan waktu 'i', cetak elemen (numberArray [i + 1] .. (ketika nilai saya adalah 1, elemen numberArray [i + 1] dicetak.) .. Misalkan, ketika i = (numberArray. length-2), elemen terakhir array dicetak. Ketika nilai 'i' masuk ke (numberArray.length-1), tidak ada nilai untuk dicetak .. Pada titik itu, 'ArrayIndexOutOfBoundsException' terjadi. Saya berharap Anda bisa mendapatkan ide. terima kasih!

GT_hash
sumber
0

Anda dapat menggunakan Opsional dalam gaya fungsional untuk menghindari NullPointerExceptiondan 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);
}

Keluaran:

AAA
NO_DATA
CCC
NO_DATA
Andrey Lavrukhin
sumber
-4

Anda tidak dapat mengulangi atau menyimpan lebih banyak data daripada panjang larik Anda. Dalam hal ini Anda dapat melakukan seperti ini:

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

Atau ini:

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