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, yaitudividedi baris 8. Di bawahnya ada pemanggilnya, yaitumaindi 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, sepertiOutOfMemoryErroratauStackOverflowError. Umumnya kamu tidak menangkapnya.Exception: masalah yang cukup masuk akal untuk diantisipasi dan ditangani oleh programmu. Di dalamnya adaRuntimeException, induk dari bug sehari-hari sepertiNullPointerException.
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:nullyang tidak kamu duga, index yang salah, atau pembagian dengan nol. Compiler tidak memaksamu menanganinya. - Checked exception meng-extend
Exceptiontetapi bukanRuntimeException(misalnyaIOException). 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
Exceptionterlalu luas. MenangkapExceptiondasar (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
atpaling atas, bukan yang paling bawah. Mulailah dari sana. - Menyamakan
ErrordenganException. Jangan mencoba memulihkan diri dariOutOfMemoryErroratauStackOverflowError; 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.