1. Pengecualian

>

Akhirnya, pengaturcara berfikir untuk menyeragamkan dan mengautomasikan pengendalian ralat. Ini berlaku apabila pengecualian dicipta. Sekarang mekanisme pengecualian mengendalikan 80% situasi luar biasa.

Jika sesetengah sarjana mengemukakan pengecualian, ia mungkin subjek disertasi kedoktorannya. Jika seorang pengaturcara datang dengannya, maka dia mungkin telah menerima tepukan mesra di belakang daripada rakan sekerja: "Nampaknya okay, bro."

Apabila ralat berlaku dalam program Java, seperti pembahagian dengan 0, beberapa perkara menarik berlaku:

Langkah satu

Objek pengecualian khas dicipta, yang mengandungi maklumat tentang ralat yang berlaku.

Segala-galanya dalam Java adalah objek, dan pengecualian tidak terkecuali 🙂 Objek pengecualian mempunyai kelas mereka sendiri, dan satu-satunya perkara yang membezakannya daripada kelas biasa ialah ia mewarisi kelas Throwable.

Langkah kedua

Objek pengecualian ialah "dilemparkan". Mungkin kata-kata di sini boleh menjadi lebih baik. "Melemparkan pengecualian" lebih seperti mencetuskan penggera kebakaran atau membunyikan amaran "DEFCON 1".

Apabila pengecualian dilemparkan ke mesin Java, operasi biasa program berhenti dan "protokol kecemasan" bermula.

Langkah ketiga

Kaedah di mana pengecualian dilemparkan keluar serta-merta. Pengecualian diserahkan kepada kaedah panggilan, yang juga keluar serta-merta. Dan seterusnya ke bawah rantai sehingga mainkaedah keluar. Apabila mainkaedah ditamatkan, begitu juga program.

Contoh:

Kod Output konsol
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Your attention, please! Preparing for the end of the world");
      endTheWorld();
      System.out.println("The world ended successfully");
   }

   public static void endTheWorld()
   {
      System.out.println("We're doing something important");
      doSomeWork(0);
      System.out.println("Everything is working well");
   }

   public static void doSomeWork(int n)
   {
      System.out.println("Nothing terrible will happen: " + n);
      System.out.println(2 / n);
      System.out.println("Nothing terrible happened: " + n);
   }
}
Your attention, please! Preparing for the end of the world
We're doing something important
Nothing terrible will happen: 0

Pengecualian berlaku pada baris 20: pembahagian dengan 0. Mesin Java serta-merta mencipta pengecualianArithmeticExceptionobjek dan "melemparkannya" ke kaedah.

Kaedah ini divide()tamat serta-merta, jadi kita tidak pernah melihat rentetan: Tiada apa-apa yang mengerikan berlaku: 0. Program ini kembali kepada kaedah endTheWorld(), dan keadaan berulang dengan sendirinya: terdapat pengecualian yang tidak dikendalikan dalam sistem, yang bermaksud bahawa endTheWorld()kaedah itu juga ditamatkan secara tidak normal. Kemudian mainkaedah ditamatkan, dan program berhenti.

Apakah tujuan pengecualian ini? Nah, anda boleh menulis kod anda sendiri untuk menangkap jenis pengecualian tertentu dan menulis logik anda sendiri untuk mengendalikan situasi luar biasa.


2. Pengecualian menangkap:try-catch

Java mempunyai mekanisme penangkapan pengecualian yang membolehkan anda menghentikan penamatan kaedah yang tidak normal ini. Ia kelihatan seperti ini:

try
{
   // Code where an exception might occur
}
catch(ExceptionType name)
{
   // Exception handling code
}

Konstruk ini dipanggil try-catchblok.

Kod di mana pengecualian mungkin berlaku dibalut dengan pendakap kerinting, didahului dengan perkataan try.

Selepas kurungan kerinting, kami mempunyai catchkata kunci dan, di dalam kurungan, pengisytiharan pembolehubah pengecualian . Ini diikuti oleh pendakap kerinting yang membalut kod untuk dilaksanakan jika pengecualian jenis yang ditentukan berlaku .

Jika tiada pengecualian dilemparkan semasa pelaksanaan " kod utama ", maka kod di dalam blok tangkapan tidak akan dilaksanakan. Jika pengecualian berlaku, maka ia akan menjadi (jika jenis pengecualian yang dilemparkan adalah sama dengan jenis pembolehubah dalam kurungan).

Contoh:

Kod Output konsol
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Hadron Collider launched");

      try
      {
         launchHadronCollider(1);
         launchHadronCollider(0);
      }
      catch(Exception e)
      {
         System.out.println("Error! Caught an exception");
         System.out.println("The planet was sucked into a black hole!");
      }

      System.out.println("The Hadron Collider stopped");
   }

   public static void launchHadronCollider(int n)
   {
      System.out.println("Everything is working well: " + n);
      System.out.println(2/n);
      System.out.println("There are no problems: " + n);
   }
}
Hadron Collider launched
Everything is working fine: 1
2
There are no problems: 1
Everything is working fine: 0
Error! Caught an exception
The planet has been sucked into a black hole!
The Hadron Collider is stopped


3. Berbilang catchblok

Berbilang blok tangkapan

Secara teori, semua jenis pengecualian boleh dilemparkan dalam blok kod. Sesetengah anda akan mahu mengendalikan satu cara, yang lain dengan cara lain, dan yang lain anda akan memutuskan untuk tidak mengendalikan sama sekali.

Pembangun Java memutuskan untuk membantu anda dan membenarkan anda menulis bukan satu tetapi banyak catchblok selepas tryblok.

try
{
   // Code where an exception might occur
}
catch (ExceptionType1 name1)
{
   // Code for handling ExceptionType1
}
catch (ExceptionType2 name2)
{
   // Code for handling ExceptionType2
}
   catch (ExceptionType3 name3)
{
   // Code for handling ExceptionType3
}

Contoh:

Kod Output konsol
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Start of main method");
      try
      {
         calculate(0);
      }
      catch (ArithmeticException e)
      {
         System.out.println("Division by 0");
      }
      catch(Exception e)
      {
         System.out.println("Caught some kind of exception");
      }

      System.out.println("End of main method");
   }

   public static void calculate(int n)
   {
      System.out.println("Start of calculate method: " + n);
      System.out.println(2/n);
      System.out.println("End of calculate method: " + n);
   }
}
Start of main method
Start of calculate method: 0
Division by 0
End of main method


4. Susunan catchblok

Pengecualian yang berlaku dalam tryblok hanya boleh ditangkap oleh satu catchblok. Anda tidak boleh mempunyai situasi pengendalian pengecualian di mana kod daripada berbilang catchblok dilaksanakan.

Tetapi susunan blok itu penting.

Anda boleh mengalami situasi di mana pengecualian boleh ditangkap oleh berbilang blok. Jika itu berlaku, maka pengecualian akan ditangkap oleh mana-mana blok tangkapantry yang datang dahulu (paling hampir dengan blok).

Bagaimanakah anda boleh menghadapi situasi di mana berbilang blok tangkapan boleh menangkap pengecualian yang sama?

Semua pengecualian tergolong dalam hierarki warisan tunggal — lihat rajah.

Hierarki pengecualian

Objek ArithmeticExceptionboleh diberikan kepada pembolehubah yang jenisnya ArithmeticExceptionatau mana-mana kelas moyangnya: RuntimeException , Exceptiondan Throwable— lihat rajah.

Kita akan bercakap lebih lanjut tentang kelas warisan dan nenek moyang di Tahap 21.

Kod ini akan disusun dengan baik:

Faedah harta pusaka:
ArithmeticException ae    = new ArithmeticException();
RuntimeException runtime  = new ArithmeticException();
Exception exception       = new ArithmeticException();
Throwable trwbl           = new ArithmeticException();

Jadi anda boleh menangkap ArithmeticExceptiondengan mana-mana 4 catchblok di atas.

Contoh 1:

Kod Output konsol
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Start of main method");
      try
      {
         calculate(0);
      }
      catch(ArithmeticException e)
      {
         System.out.println("Division by 0");
      }
      catch(Exception e)
      {
         System.out.println("Caught some kind of exception");
      }

      System.out.println("End of main method");
   }

   public static void calculate(int n)
   {
      System.out.println("Start of calculate method: " + n);
      System.out.println(2/n);
      System.out.println("End of calculate method: " + n);
   }
}
Start of main method
Start of calculate method: 0
Division by 0
End of main method

Dalam contoh ini, ArithmeticExceptionboleh ditangkap oleh kedua-dua catch (Exception e)dan catch (ArithmeticException e)blok. Ia akan ditangkap oleh blok yang paling hampir dengan tryblok - blok pertama catch.

Untuk mengelakkan kejutan, sebaiknya letakkan catchblok yang boleh menangkap hampir setiap pengecualian berhampiran penghujung senarai catchblok.

Jenis ini Throwablesecara amnya mampu menangkap setiap pengecualian yang mungkin di Jawa . Jika anda meletakkannya dalam catchblok pertama, maka kod itu tidak akan dikompil, kerana pengkompil mengetahui bahawa terdapat blok kod yang tidak boleh dicapai.