Menu

Exception Java: Error, Stack Trace, dan Melempar Exception

Apa itu exception di Java, cara membaca stack trace, perbedaan checked dan unchecked, hierarki exception, dan cara melempar exception buatanmu sendiri.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Apa Itu Exception

Exception adalah cara Java mengatakan "ada yang salah dan aku tidak bisa melanjutkan seperti biasa." Daripada mengembalikan nilai yang keliru atau diam-diam merusak datamu, runtime membuat objek exception yang menjelaskan masalahnya lalu melemparnya. Eksekusi normal berhenti di titik itu, dan Java mulai mencari kode yang tahu cara menangani situasinya.

Kalau tidak ada yang menanganinya, exception itu sampai ke bagian paling atas programmu, JVM mencetak stack trace, dan prosesnya berhenti dengan status bukan nol.

Perhatikan bahwa "after" tidak pernah tercetak. Begitu numbers[5] dievaluasi, ArrayIndexOutOfBoundsException dilempar dan sisa main ditinggalkan. Mengakses melewati index valid terakhir sebuah array adalah salah satu penyebab exception yang paling sering.

Membaca Stack Trace

Saat sebuah exception tidak ditangani, kamu akan mendapat output seperti ini. Kelihatannya menakutkan, padahal isinya hanya sebuah daftar:

Exception in thread "main" java.lang.ArithmeticException: / by zero
	at Main.divide(Main.java:8)
	at Main.main(Main.java:4)

Baca dari atas ke bawah:

  • Baris pertama adalah tipe (ArithmeticException) dan pesan (/ by zero).
  • Setiap baris at ... adalah stack frame. Yang paling atas adalah tempat exception benar-benar dilempar, yaitu divide di baris 8. Di bawahnya ada pemanggilnya, yaitu main di baris 4.

Baris at paling atas adalah tempat pertama yang kamu periksa. Frame di bawahnya menjawab pertanyaan "bagaimana kita bisa sampai di sini?"

Jalankan ini, dan trace-nya langsung menunjuk ke baris a / b, lalu menampilkan main sebagai pemanggilnya. Rantai pemanggilan itu adalah alat debugging paling berguna yang diberikan Java secara gratis.

Hierarki Exception

Setiap exception adalah objek, dan semuanya diturunkan dari Throwable. Dua cabang yang penting:

  • Error: masalah serius yang dimunculkan JVM, seperti OutOfMemoryError atau StackOverflowError. Umumnya kamu tidak menangkapnya.
  • Exception: masalah yang cukup masuk akal untuk diantisipasi dan ditangani oleh programmu. Di dalamnya ada RuntimeException, induk dari bug sehari-hari seperti NullPointerException.
Throwable
├── Error                 (don't catch: OutOfMemoryError, StackOverflowError)
└── Exception
    ├── IOException        (checked)
    ├── SQLException       (checked)
    └── RuntimeException   (unchecked)
        ├── NullPointerException
        ├── ArithmeticException
        └── ArrayIndexOutOfBoundsException

Karena semuanya class sungguhan, sebuah exception bisa membawa pesan dan kamu bisa menanyakan informasi tentang dirinya:

getMessage() mengembalikan teks setelah titik dua di stack trace; getClass().getSimpleName() memberimu nama tipe exception-nya.

Checked vs Unchecked

Inilah perbedaan yang paling sering membingungkan pendatang baru.

  • Unchecked exception meng-extend RuntimeException. Biasanya ini berarti ada bug di kodemu: null yang tidak kamu duga, index yang salah, atau pembagian dengan nol. Compiler tidak memaksamu menanganinya.
  • Checked exception meng-extend Exception tetapi bukan RuntimeException (misalnya IOException). Exception ini mewakili kondisi di luar kendalimu, seperti file yang hilang atau koneksi jaringan yang terputus. Compiler memaksamu untuk menangkapnya atau mendeklarasikannya.

Kalau sebuah method bisa melempar checked exception, method itu harus menyatakannya dengan throws, dan setiap pemanggilnya harus menanganinya:

Hapus throws Exception dari main, maka kodenya bahkan tidak akan bisa dikompilasi. Itulah compiler yang menegakkan kontrak checked exception. Unchecked exception tidak pernah membutuhkan ini.

Melempar Exception Sendiri

Kamu tidak hanya bereaksi terhadap exception, kamu juga bisa memunculkannya. Pakai throw dengan objek exception baru untuk menandakan bahwa sebuah argumen atau state tidak valid. Cara ini jauh lebih baik daripada mengembalikan nilai ajaib seperti -1 lalu berharap pemanggilnya memeriksanya.

Selalu sertakan pesan yang menjelaskan apa yang salah, idealnya beserta nilai yang bermasalah. Dirimu di masa depan yang membaca stack trace-nya akan berterima kasih. IllegalArgumentException dan IllegalStateException adalah dua exception yang paling sering kamu pakai saat memvalidasi input.

Jebakan Umum

  • Menelan exception. Menangkap exception lalu tidak melakukan apa-apa (blok kosong) menyembunyikan bug. Minimal catat di log; biasanya kamu sebaiknya menanganinya atau melemparnya ulang.
  • Menangkap Exception terlalu luas. Menangkap Exception dasar (atau lebih buruk lagi, Throwable) bisa menutupi masalah yang tidak berniat kamu tangani. Tangkap tipe spesifik yang kamu harapkan.
  • Membaca trace dari bawah ke atas. Frame yang paling relevan adalah baris at paling atas, bukan yang paling bawah. Mulailah dari sana.
  • Menyamakan Error dengan Exception. Jangan mencoba memulihkan diri dari OutOfMemoryError atau StackOverflowError; perbaiki penyebab dasarnya.

Berikutnya: try-catch

Sekarang kamu sudah tahu apa itu exception dan cara membacanya. Halaman berikutnya membahas cara benar-benar menanganinya: membungkus kode berisiko di dalam blok try, memulihkan keadaan di catch, dan menjalankan kode pembersihan di finally supaya programmu tetap berjalan, bukan crash.

Pertanyaan yang sering diajukan

Apa itu exception di Java?

Exception adalah objek yang mewakili masalah yang terdeteksi saat program berjalan, misalnya pembagian dengan nol, mengakses index melewati ujung array, atau memanggil method pada null. Saat masalah itu terjadi, Java melempar exception: alur normal berhenti dan Java mencari kode yang bisa menangani-nya. Kalau tidak ada yang menanganinya, program mencetak stack trace lalu berhenti.

Apa perbedaan checked exception dan unchecked exception di Java?

Checked exception (subclass dari Exception tetapi bukan dari RuntimeException, misalnya IOException) wajib ditangkap atau dideklarasikan dengan throws, dan compiler memaksakannya. Unchecked exception (subclass dari RuntimeException, misalnya NullPointerException dan ArrayIndexOutOfBoundsException) biasanya menandakan bug pemrograman dan tidak perlu dideklarasikan. Error (seperti OutOfMemoryError) juga termasuk unchecked dan umumnya tidak dimaksudkan untuk ditangkap.

Bagaimana cara membaca stack trace di Java?

Baca dari atas ke bawah. Baris pertama menyebutkan tipe exception dan pesannya (misalnya java.lang.ArithmeticException: / by zero). Setiap baris at ... di bawahnya adalah stack frame yang menunjukkan method, file, dan nomor baris, dimulai dari tempat exception dilempar lalu mundur melewati para pemanggilnya. Baris at paling atas hampir selalu menjadi tempat pertama yang perlu kamu periksa.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai