Menguasai Penanganan Pengecualian Java: Mengelola Kesalahan Tak Terduga dengan Elegan
Sebuah pengecualian (atau peristiwa luar biasa) adalah masalah yang timbul selama eksekusi program. Ketika Pengecualian terjadi, alur normal program terganggu dan program/Aplikasi berakhir secara tidak normal, yang tidak disarankan, oleh karena itu, pengecualian ini harus ditangani.
Sebuah pengecualian dapat terjadi karena banyak alasan yang berbeda. Berikut adalah beberapa skenario di mana pengecualian terjadi.
Pengguna telah memasukkan data yang tidak valid.
Sebuah berkas yang perlu dibuka tidak dapat ditemukan.
Koneksi jaringan telah terputus di tengah komunikasi atau JVM kehabisan memori.
Beberapa pengecualian ini disebabkan oleh kesalahan pengguna, yang lain oleh kesalahan programmer, dan yang lain oleh sumber daya fisik yang gagal dengan cara tertentu.
Berdasarkan ini, kita memiliki tiga kategori Pengecualian. Anda perlu memahami mereka untuk mengetahui cara penanganan pengecualian bekerja di Java.
Pengecualian yang Diperiksa (Checked exceptions) – Sebuah pengecualian yang diperiksa adalah pengecualian yang diperiksa (memberi tahu) oleh compiler pada waktu kompilasi, ini juga disebut pengecualian waktu kompilasi. Pengecualian ini tidak dapat diabaikan dengan mudah, programmer harus menangani (memproses) pengecualian ini.
Misalnya, jika Anda menggunakan kelas FileReader dalam program Anda untuk membaca data dari berkas, jika berkas yang ditentukan dalam konstruktornya tidak ada, maka FileNotFoundException terjadi, dan compiler meminta programmer untuk menangani pengecualian.
Contoh
Live Demo
import java.io.File; import java.io.FileReader; public class FilenotFound_Demo { public static void main(String args[]) { File file = new File("E://file.txt"); FileReader fr = new FileReader(file); } } Jika Anda mencoba mengkompilasi program di atas, Anda akan mendapatkan pengecualian berikut.
Keluaran
C:\>javac FilenotFound_Demo.java FilenotFound_Demo.java:8: error: unreported exception FileNotFoundException; must be caught or declared to be thrown FileReader fr = new FileReader(file); ^ 1 error
Catatan – Karena metode read() dan close() dari kelas FileReader melempar IOException, Anda dapat melihat bahwa compiler memberi tahu untuk menangani IOException, bersama dengan FileNotFoundException.
Pengecualian Tidak Diperiksa (Unchecked exceptions) – Sebuah pengecualian yang tidak diperiksa adalah pengecualian yang terjadi pada waktu eksekusi. Ini juga disebut Pengecualian Runtime. Ini termasuk kesalahan pemrograman, seperti kesalahan logika atau penggunaan API yang tidak tepat. Pengecualian runtime diabaikan pada waktu kompilasi.
Misalnya, jika Anda telah mendeklarasikan array dengan ukuran 5 dalam program Anda, dan mencoba memanggil elemen ke-6th dari array maka ArrayIndexOutOfBoundsException terjadi.
Contoh
Live Demo
public class Unchecked_Demo { public static void main(String args[]) { int num[] = {1, 2, 3, 4}; System.out.println(num[5]); } } Jika Anda mengkompilasi dan menjalankan program di atas, Anda akan mendapatkan pengecualian berikut.
Keluaran
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 at Exceptions.Unchecked_Demo.main(Unchecked_Demo.java:8)
Errors – Ini bukanlah pengecualian sama sekali, melainkan masalah yang timbul di luar kontrol pengguna atau programmer. Errors biasanya diabaikan dalam kode Anda karena Anda jarang dapat melakukan sesuatu terhadap error. Misalnya, jika terjadi stack overflow, error akan muncul. Mereka juga diabaikan pada waktu kompilasi.
Hierarki Pengecualian
Semua kelas pengecualian adalah subjenis dari kelas java.lang.Exception. Kelas pengecualian adalah subclass dari kelas Throwable. Selain kelas pengecualian, ada subclass lain bernama Error yang berasal dari kelas Throwable.
Errors adalah kondisi abnormal yang terjadi dalam hal kegagalan yang parah, ini tidak ditangani oleh program Java. Errors dihasilkan untuk menunjukkan error yang dihasilkan oleh lingkungan runtime. Contoh: JVM kehabisan memori. Biasanya, program tidak dapat pulih dari errors.
Kelas Exception memiliki dua subclass utama: kelas IOException dan kelas RuntimeException.
Berikut adalah daftar Pengecualian Built-in Java yang paling umum yang diperiksa dan tidak diperiksa.
Metode Pengecualian
Berikut adalah daftar metode penting yang tersedia dalam kelas Throwable.
| Sr.No. | Metode & Deskripsi |
| 1 | public String getMessage() Mengembalikan pesan detail tentang pengecualian yang telah terjadi. Pesan ini diinisialisasi dalam konstruktor Throwable. |
| 2 | public Throwable getCause() Mengembalikan penyebab pengecualian yang direpresentasikan oleh objek Throwable. |
| 3 | public String toString() Mengembalikan nama kelas yang digabungkan dengan hasil getMessage(). |
| 4 | public void printStackTrace() Mencetak hasil toString() bersama dengan stack trace ke System.err, aliran output error. |
| 5 | public StackTraceElement [] getStackTrace() Mengembalikan array yang berisi setiap elemen pada stack trace. Elemen pada indeks 0 mewakili puncak tumpukan panggilan, dan elemen terakhir dalam array mewakili metode di dasar tumpukan panggilan. |
| 6 | public Throwable fillInStackTrace() Mengisi stack trace dari objek Throwable ini dengan stack trace saat ini, menambahkan ke informasi sebelumnya dalam stack trace. |
Menangkap Pengecualian
Sebuah metode menangkap pengecualian menggunakan kombinasi kata kunci try dan catch. Blok try/cast ditempatkan di sekitar kode yang mungkin menghasilkan pengecualian. Kode dalam blok try/cast disebut sebagai kode yang dilindungi, dan sintaks untuk menggunakan try/cast terlihat sebagai berikut:
Sintaks
try { // Kode yang dilindungi } catch (ExceptionName e1) { // Blok tangkap } Kode yang rentan terhadap pengecualian ditempatkan dalam blok try. Ketika pengecualian terjadi, pengecualian tersebut ditangani oleh blok tangkap yang terkait. Setiap blok try harus segera diikuti oleh blok tangkap atau blok finally.
Pernyataan tangkap melibatkan mendeklarasikan tipe pengecualian yang Anda coba tangkap. Jika pengecualian terjadi dalam kode yang dilindungi, blok tangkap (atau blok-blok) yang mengikuti try akan diperiksa. Jika tipe pengecualian yang terjadi tercantum dalam blok tangkap, pengecualian diteruskan ke blok tangkap seolah-olah argumen diteruskan ke parameter metode.
Contoh
Berikut adalah array yang dideklarasikan dengan 2 elemen. Kemudian kode mencoba mengakses elemen ke-3rd dari array yang melempar pengecualian.
Live Demo
// Nama File : ExcepTest.java import java.io.*; public class ExcepTest { public static void main(String args[]) { try { int a[] = new int[2]; System.out.println("Akses elemen tiga :" + a[3]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Pengecualian dilempar :" + e); } System.out.println("Di luar blok"); } } Ini akan menghasilkan hasil berikut:
Keluaran
Pengecualian dilempar :java.lang.ArrayIndexOutOfBoundsException: 3 Di luar blok
Beberapa Blok Tangkap
Sebuah blok try dapat diikuti oleh beberapa blok tangkap. Sintaks untuk beberapa blok tangkap terlihat sebagai berikut:
Sintaks
try { // Kode yang dilindungi } catch (ExceptionType1 e1) { // Blok tangkap } catch (ExceptionType2 e2) { // Blok tangkap } catch (ExceptionType3 e3) { // Blok tangkap } Pernyataan sebelumnya menunjukkan tiga blok tangkap, tetapi Anda dapat memiliki sebanyak yang Anda inginkan setelah satu try. Jika pengecualian terjadi dalam kode yang dilindungi, pengecualian dilempar ke blok tangkap pertama dalam daftar. Jika tipe data pengecualian yang dilempar cocok dengan ExceptionType1, ia ditangkap di sana. Jika tidak, pengecualian diteruskan ke pernyataan tangkap kedua. Ini berlanjut sampai pengecualian ditangkap atau melewati semua tangkap, dalam hal ini metode saat ini berhenti dieksekusi dan pengecualian dilempar ke metode sebelumnya di tumpukan panggilan.
Contoh
Berikut adalah potongan kode yang menunjukkan cara menggunakan beberapa pernyataan try/cast.
try { file = new FileInputStream(fileName); x = (byte) file.read(); } catch (IOException i) { i.printStackTrace(); return -1; } catch (FileNotFoundException f) // Tidak valid! { f.printStackTrace(); return -1; } Menangkap Beberapa Tipe Pengecualian
Sejak Java 7, Anda dapat menangani lebih dari satu pengecualian menggunakan satu blok tangkap, fitur ini menyederhanakan kode. Berikut adalah cara Anda melakukannya:
catch (IOException|FileNotFoundException ex) { logger.log(ex); throw ex; Kata Kunci Throws/Throw
Jika suatu metode tidak menangani pengecualian yang diperiksa, metode harus mendeklarasikannya menggunakan kata kunci throws. Kata kunci throws muncul di akhir tanda tangan metode.
Anda dapat melempar pengecualian, baik yang baru diinstantiasi atau pengecualian yang baru saja Anda tangkap, dengan menggunakan kata kunci throw.
Coba pahami perbedaan antara kata kunci throws dan throw, throws digunakan untuk menunda penanganan pengecualian yang diperiksa dan throw digunakan untuk memanggil pengecualian secara eksplisit.
Metode berikut mendeklarasikan bahwa ia melempar RemoteException:
Contoh
import java.io.*; public class className { public void deposit(double amount) throws RemoteException { // Implementasi metode throw new RemoteException(); } // Sisa definisi kelas } Sebuah metode dapat mendeklarasikan bahwa ia melempar lebih dari satu pengecualian, dalam hal ini pengecualian dideklarasikan dalam daftar yang dipisahkan oleh koma. Misalnya, metode berikut mendeklarasikan bahwa ia melempar RemoteException dan InsufficientFundsException:
Contoh
import java.io.*; public class className { public void withdraw(double amount) throws RemoteException, InsufficientFundsException { // Implementasi metode } // Sisa definisi kelas } Blok Finally
Blok finally mengikuti blok try atau blok tangkap. Blok finally selalu dieksekusi, terlepas dari terjadinya Pengecualian.
Menggunakan blok finally memungkinkan Anda menjalankan pernyataan pembersihan apa pun yang ingin Anda eksekusi, apa pun yang terjadi dalam kode yang dilindungi.
Blok finally muncul di akhir blok tangkap dan memiliki sintaks sebagai berikut:
Sintaks
try { // Kode yang dilindungi } catch (ExceptionType1 e1) { // Blok tangkap } catch (ExceptionType2 e2) { // Blok tangkap } catch (ExceptionType3 e3) { // Blok tangkap }finally { // Blok finally selalu dieksekusi. } Contoh
Live Demo
public class ExcepTest { public static void main(String args[]) { int a[] = new int[2]; try { System.out.println("Akses elemen tiga :" + a[3]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Pengecualian dilempar :" + e); }finally { a[0] = 6; System.out.println("Nilai elemen pertama: " + a[0]); System.out.println("Pernyataan finally dieksekusi"); } } } Ini akan menghasilkan hasil berikut:
Keluaran
Pengecualian dilempar :java.lang.ArrayIndexOutOfBoundsException: 3 Nilai elemen pertama: 6 Pernyataan finally dieksekusi
Perhatikan hal berikut:
Klausa tangkap tidak dapat ada tanpa pernyataan try.
Tidak wajib memiliki klausa finally setiap kali blok try/cast ada.
Blok try tidak dapat ada tanpa klausa tangkap atau klausa finally.
Kode apa pun tidak dapat ada di antara blok try, catch, finally.
try-with-resources
Secara umum, ketika kita menggunakan sumber daya seperti aliran, koneksi, dll. kita harus menutupnya secara eksplisit menggunakan blok finally. Dalam program berikut, kita membaca data dari berkas menggunakan FileReader dan kita menutupnya menggunakan blok finally.
Contoh
import java.io.File; import java.io.FileReader; import java.io.IOException; public class ReadData_Demo { public static void main(String args[]) { FileReader fr = null; try { File file = new File("file.txt"); fr = new FileReader(file); char [] a = new char[50]; fr.read(a); // membaca konten ke array for(char c : a) System.out.print(c); // mencetak karakter satu per satu } catch (IOException e) { e.printStackTrace(); }finally { try { fr.close(); } catch (IOException ex) { ex.printStackTrace(); } } } } try-with-resources, juga disebut pengelolaan sumber daya otomatis, adalah mekanisme penanganan pengecualian baru yang diperkenalkan di Java 7, yang secara otomatis menutup sumber daya yang digunakan dalam blok try-cast.
Untuk menggunakan pernyataan ini, Anda cukup mendeklarasikan sumber daya yang diperlukan dalam tanda kurung, dan sumber daya yang dibuat akan ditutup secara otomatis di akhir blok. Berikut adalah sintaks pernyataan try-with-resources.
Sintaks
try(FileReader fr = new FileReader("path berkas")) { // gunakan sumber daya } catch () { // isi blok tangkap } } Berikut adalah program yang membaca data dalam berkas menggunakan pernyataan try-with-resources.
Contoh
import java.io.FileReader; import java.io.IOException; public class Try_withDemo { public static void main(String args[]) { try(FileReader fr = new FileReader("E://file.txt")) { char [] a = new char[50]; fr.read(a); // membaca konten ke array for(char c : a) System.out.print(c); // mencetak karakter satu per satu } catch (IOException e) { e.printStackTrace(); } } } Beberapa poin yang perlu diingat saat bekerja dengan pernyataan try-with-resources.
Untuk menggunakan kelas dengan pernyataan try-with-resources, kelas harus mengimplementasikan antarmuka AutoCloseable dan metode close() dari kelas tersebut akan dipanggil secara otomatis pada runtime.
Anda dapat mendeklarasikan lebih dari satu kelas dalam pernyataan try-with-resources.
Saat Anda mendeklarasikan beberapa kelas dalam blok try dari pernyataan try-with-resources, kelas-kelas ini ditutup dalam urutan terbalik.
Kecuali deklarasi sumber daya dalam tanda kurung, semuanya sama dengan blok try/cast normal dari blok try.
Sumber daya yang dideklarasikan dalam try diinstantiasi tepat sebelum awal blok try.
Sumber daya yang dideklarasikan di blok try secara implisit dideklarasikan sebagai final.
Pengecualian yang Didefinisikan Pengguna
Anda dapat membuat pengecualian Anda sendiri di Java. Perhatikan poin berikut saat menulis kelas pengecualian Anda sendiri:
Semua pengecualian harus merupakan anak dari Throwable.
Jika Anda ingin menulis pengecualian yang diperiksa yang secara otomatis diberlakukan oleh Aturan Tangani atau Deklarasikan, Anda perlu memperluas kelas Exception.
Jika Anda ingin menulis pengecualian runtime, Anda perlu memperluas kelas RuntimeException.
Kita dapat mendefinisikan kelas Pengecualian kita sendiri sebagai berikut:
class MyException extends Exception { } Anda hanya perlu memperluas kelas Exception yang telah ditentukan sebelumnya untuk membuat Pengecualian Anda sendiri. Ini dianggap sebagai pengecualian yang diperiksa. Kelas InsufficientFundsException berikut adalah pengecualian yang ditentukan pengguna yang memperluas kelas Exception, sehingga menjadi pengecualian yang diperiksa. Kelas pengecualian seperti kelas apa pun, yang berisi bidang dan metode yang berguna.
Contoh
// Nama File InsufficientFundsException.java import java.io.*; public class InsufficientFundsException extends Exception { private double amount; public InsufficientFundsException(double amount) { this.amount = amount; } public double getAmount() { return amount; } } Untuk menunjukkan penggunaan pengecualian yang ditentukan pengguna kita, kelas CheckingAccount berikut berisi metode withdraw() yang melempar InsufficientFundsException.
// Nama File CheckingAccount.java import java.io.*; public class CheckingAccount { private double balance; private int number; public CheckingAccount(int number) { this.number = number; } public void deposit(double amount) { balance += amount; } public void withdraw(double amount) throws InsufficientFundsException { if(amount <= balance) { balance -= amount; }else { double needs = amount - balance; throw new InsufficientFundsException(needs); } } public double getBalance() { return balance; } public int getNumber() { return number; } } Program BankDemo berikut menunjukkan pemanggilan metode deposit() dan withdraw() dari CheckingAccount.
// Nama File BankDemo.java public class BankDemo { public static void main(String [] args) { CheckingAccount c = new CheckingAccount(101); System.out.println("Menyetor $500..."); c.deposit(500.00); try { System.out.println("\nMengambil $100..."); c.withdraw(100.00); System.out.println("\nMengambil $600..."); c.withdraw(600.00); } catch (InsufficientFundsException e) { System.out.println("Maaf, Anda kekurangan $" + e.getAmount()); e.printStackTrace(); } } } Kompilasi ketiga file di atas dan jalankan BankDemo. Ini akan menghasilkan hasil berikut:
Keluaran
Menyetor $500... Mengambil $100... Mengambil $600... Maaf, Anda kekurangan $200.0 InsufficientFundsException at CheckingAccount.withdraw(CheckingAccount.java:25) at BankDemo.main(BankDemo.java:13)
Pengecualian Umum
Di Java, mungkin untuk mendefinisikan dua kategori Pengecualian dan Error.
Pengecualian JVM – Ini adalah pengecualian/error yang secara eksklusif atau logis dilempar oleh JVM. Contoh: NullPointerException, ArrayIndexOutOfBoundsException, ClassCastException.
Pengecualian Programatik – Pengecualian ini dilempar secara eksplisit oleh aplikasi atau programmer API. Contoh: IllegalArgumentException, IllegalStateException.