1. Jenis pengecualian

Semua pengecualian dibagi menjadi 4 jenis, yang sebenarnya adalah kelas yang saling mewarisi.

Throwablekelas

Kelas dasar untuk semua pengecualian adalah Throwablekelas. Kelas Throwableberisi kode yang menulis tumpukan panggilan saat ini (pelacakan tumpukan dari metode saat ini) ke sebuah array. Kami akan mempelajari apa itu pelacakan tumpukan nanti.

Operator lemparan hanya dapat menerima objek yang berasal dari Throwablekelas. Dan meskipun Anda secara teoritis dapat menulis kode seperti throw new Throwable();, biasanya tidak ada yang melakukan ini. Tujuan utama kelas Throwableadalah untuk memiliki kelas induk tunggal untuk semua pengecualian.

Errorkelas

Kelas pengecualian berikutnya adalah Errorkelas yang secara langsung mewarisi Throwablekelas tersebut. Mesin Java membuat objek kelas Error(dan turunannya) ketika masalah serius terjadi . Misalnya, kerusakan perangkat keras, memori tidak mencukupi, dll.

Biasanya, sebagai programmer, tidak ada yang dapat Anda lakukan dalam situasi di mana kesalahan seperti itu (jenis yang Errorharus dibuang) telah terjadi dalam program: kesalahan ini terlalu serius. Yang dapat Anda lakukan hanyalah memberi tahu pengguna bahwa program mogok dan/atau menulis semua informasi yang diketahui tentang kesalahan ke log program.

Exceptionkelas

Kelas Exceptionand RuntimeExceptionadalah untuk kesalahan umum yang terjadi dalam pengoperasian banyak metode. Tujuan dari setiap pengecualian yang dilemparkan adalah untuk ditangkap oleh catchblok yang tahu cara menanganinya dengan benar.

Ketika suatu metode tidak dapat menyelesaikan pekerjaannya karena alasan tertentu, ia harus segera memberi tahu metode pemanggil dengan melemparkan pengecualian dari jenis yang sesuai.

Dengan kata lain, jika sebuah variabel sama dengan null, metode akan melempar NullPointerException. Jika argumen yang salah diteruskan ke metode, itu akan membuang InvalidArgumentException. Jika metode ini secara tidak sengaja membagi dengan nol, itu akan membuang ArithmeticException.

RuntimeExceptionkelas

RuntimeExceptionsadalah subset dari Exceptions. Kami bahkan dapat mengatakan bahwa RuntimeExceptionini adalah versi ringan dari pengecualian biasa ( Exception) — lebih sedikit persyaratan dan batasan yang dikenakan pada pengecualian tersebut

Anda akan mempelajari perbedaan antara Exceptiondan RuntimeExceptionnanti.


2. Throws: memeriksa pengecualian

Semua pengecualian Java terbagi dalam 2 kategori: dicentang dan tidak dicentang .

Semua pengecualian yang mewarisi RuntimeExceptionatau Errordianggap sebagai pengecualian yang tidak dicentang . Semua lainnya diperiksa pengecualian .

Penting!

Dua puluh tahun setelah pengecualian diperiksa diperkenalkan, hampir setiap programmer Java menganggap ini sebagai bug. Dalam kerangka modern populer, 95% dari semua pengecualian tidak dicentang. Bahasa C#, yang hampir menyalin Java persis, tidak menambahkan pengecualian yang dicentang .

Apa perbedaan utama antara pengecualian yang dicentang dan tidak dicentang ?

Ada persyaratan tambahan yang dikenakan pada pengecualian yang diperiksa . Secara kasar, mereka adalah ini:

Persyaratan 1

Jika sebuah metode melontarkan pengecualian yang dicentang , ia harus menunjukkan jenis pengecualian dalam tanda tangannya . Dengan begitu, setiap metode yang memanggilnya menyadari bahwa "pengecualian yang berarti" ini mungkin terjadi di dalamnya.

Tunjukkan pengecualian yang dicentang setelah parameter metode setelah throwskata kunci (jangan gunakan throwkata kunci secara tidak sengaja). Ini terlihat seperti ini:

type method (parameters) throws exception

Contoh:

pengecualian diperiksa pengecualian yang tidak dicentang
public void calculate(int n) throws Exception
{
   if (n == 0)
      throw new Exception("n is null!");
}
public void calculate(n)
{
   if (n == 0)
      throw new RuntimeException("n is null!");
}

Pada contoh di sebelah kanan, kode kita melontarkan pengecualian yang tidak dicentang — tidak diperlukan tindakan tambahan. Pada contoh di sebelah kiri, metode melontarkan pengecualian yang dicentang , sehingga throwskata kunci ditambahkan ke tanda tangan metode bersama dengan jenis pengecualian.

Jika suatu metode mengharapkan untuk membuang beberapa pengecualian yang diperiksa , semuanya harus ditentukan setelah throwskata kunci, dipisahkan dengan koma. Urutannya tidak penting. Contoh:

public void calculate(int n) throws Exception, IOException
{
   if (n == 0)
      throw new Exception("n is null!");
   if (n == 1)
      throw new IOException("n is 1");
}

Persyaratan 2

Jika Anda memanggil metode yang telah memeriksa pengecualian pada tanda tangannya, Anda tidak dapat mengabaikan fakta bahwa metode tersebut melemparkannya.

Anda harus menangkap semua pengecualian tersebut dengan menambahkan catchblok untuk masing-masing, atau dengan menambahkannya ke throwsklausa untuk metode Anda.

Seolah-olah kita mengatakan, " Pengecualian ini sangat penting sehingga kita harus menangkapnya. Dan jika kita tidak tahu cara menanganinya, maka siapa pun yang mungkin memanggil metode kita harus diberi tahu bahwa pengecualian tersebut dapat terjadi di dalamnya.

Contoh:

Bayangkan kita sedang menulis metode untuk menciptakan dunia yang dihuni oleh manusia. Jumlah awal orang dilewatkan sebagai argumen. Jadi kita perlu menambahkan pengecualian jika jumlah orang terlalu sedikit.

Menciptakan Bumi Catatan
public void createWorld(int n) throws EmptyWorldException, LonelyWorldException
{
   if (n == 0)
      throw new EmptyWorldException("There are no people!");
   if (n == 1)
      throw new LonelyWorldException ("There aren't enough people!");
   System.out.println("A wonderful world was created. Population: " + n);
}
Metode ini berpotensi melontarkan dua pengecualian yang diperiksa :

  • Pengecualian Dunia Kosong
  • Pengecualian Dunia Kesepian

Panggilan metode ini dapat ditangani dengan 3 cara:

1. Jangan tangkap pengecualian apa pun

Ini paling sering dilakukan ketika metode tidak mengetahui cara menangani situasi dengan benar.

Kode Catatan
public void createPopulatedWorld(int population)
throws EmptyWorldException, LonelyWorldException
{
   createWorld(population);
}
Metode pemanggilan tidak menangkap pengecualian dan harus memberi tahu orang lain tentangnya: ia menambahkannya ke klausanya throwssendiri

2. Tangkap beberapa pengecualian

Kami menangani kesalahan yang dapat kami tangani. Tapi yang tidak kami mengerti, kami melemparkannya ke metode pemanggilan. Untuk melakukan ini, kita perlu menambahkan nama mereka ke klausa throws:

Kode Catatan
public void createNonEmptyWorld(int population)
throws EmptyWorldException
{
   try
   {
      createWorld(population);
   }
   catch (LonelyWorldException e)
   {
      e.printStackTrace();
   }
}
Penelepon menangkap hanya satu pengecualian yang dicentangLonelyWorldException — . Pengecualian lain harus ditambahkan ke tanda tangannya, yang menunjukkannya setelah throwskata kunci

3. Tangkap semua pengecualian

Jika metode tidak membuang pengecualian ke metode pemanggilan, maka metode pemanggilan selalu yakin bahwa semuanya bekerja dengan baik. Dan itu tidak akan dapat mengambil tindakan apa pun untuk memperbaiki situasi luar biasa.

Kode Catatan
public void createAnyWorld(int population)
{
   try
   {
      createWorld(population);
   }
   catch (LonelyWorldException e)
   {
      e.printStackTrace();
   }
   catch (EmptyWorldException e)
   {
      e.printStackTrace();
   }
}
Semua pengecualian ditangkap dalam metode ini. Penelepon akan yakin bahwa semuanya berjalan dengan baik.


3. Menangkap banyak pengecualian

Pemrogram sangat benci untuk menggandakan kode. Mereka bahkan menemukan prinsip pengembangan yang sesuai — KERING : Jangan Ulangi Diri Anda Sendiri. Namun saat menangani pengecualian, sering kali sebuah tryblok diikuti oleh beberapa catchblok dengan kode yang sama.

Atau mungkin ada 3 catchblok dengan kode yang sama dan 2 catchblok lainnya dengan kode identik lainnya. Ini adalah situasi standar ketika proyek Anda menangani pengecualian secara bertanggung jawab.

Dimulai dengan versi 7, bahasa Java menambahkan kemampuan untuk menentukan beberapa jenis pengecualian dalam satu catchblok. Kira-kira seperti ini:

try
{
   // Code where an exception might occur
}
catch (ExceptionType1 | ExceptionType2 | ExceptionType3 name)
{
   // Exception handling code
}

Anda dapat memiliki blok sebanyak catchyang Anda inginkan. Namun, satu catchblok tidak dapat menentukan pengecualian yang mewarisi satu sama lain. Dengan kata lain, Anda tidak dapat menulis catch ( Exception| RuntimeExceptione), karena RuntimeExceptionclass mewarisi Exception.