1. Ngoại lệ

>

Cuối cùng, các lập trình viên đã nghĩ đến việc tiêu chuẩn hóa và tự động hóa việc xử lý lỗi. Điều này xảy ra khi các ngoại lệ được phát minh. Bây giờ cơ chế ngoại lệ xử lý 80% các tình huống ngoại lệ.

Nếu một học giả nào đó đưa ra các ngoại lệ, thì đó có thể là chủ đề của luận án tiến sĩ của anh ấy hoặc cô ấy. Nếu một lập trình viên nghĩ ra nó, thì anh ta có thể đã nhận được một cái vỗ nhẹ thân thiện từ đồng nghiệp: "Có vẻ ổn đấy, anh bạn."

Khi xảy ra lỗi trong một chương trình Java, chẳng hạn như chia cho 0, một số điều tuyệt vời sẽ xảy ra:

Bước một

Một đối tượng ngoại lệ đặc biệt được tạo, chứa thông tin về lỗi đã xảy ra.

Mọi thứ trong Java đều là đối tượng và ngoại lệ cũng không phải ngoại lệ 🙂 Đối tượng ngoại lệ có các lớp riêng và điều duy nhất phân biệt chúng với các lớp thông thường là chúng kế thừa lớp Throwable.

Bước hai

Đối tượng ngoại lệ là "ném". Có lẽ từ ngữ ở đây có thể tốt hơn. "Ném một ngoại lệ" giống như kích hoạt chuông báo cháy hoặc phát ra âm thanh cảnh báo "DEFCON 1".

Khi một ngoại lệ được ném vào máy Java, hoạt động bình thường của chương trình sẽ dừng lại và "các giao thức khẩn cấp" bắt đầu.

Bước thứ ba

Phương thức ném ngoại lệ sẽ thoát ngay lập tức. Ngoại lệ được chuyển đến phương thức gọi, phương thức này cũng thoát ngay lập tức. Và cứ tiếp tục như vậy cho đến khi mainphương thức thoát. Khi mainphương thức kết thúc, chương trình cũng vậy.

Ví dụ:

Mã số Đầu ra bảng điều khiển
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

Một ngoại lệ xảy ra ở dòng 20: chia cho 0. Máy Java ngay lập tức tạo một ngoại lệ — một ArithmeticExceptionđối tượng và "ném" nó vào phương thức.

Phương divide()thức kết thúc ngay lập tức, vì vậy chúng ta không bao giờ thấy chuỗi: Không có gì khủng khiếp xảy ra: 0. Chương trình quay lại phương endTheWorld()thức và tình huống lặp lại: có một ngoại lệ chưa được xử lý trong hệ thống, có nghĩa là phương endTheWorld()thức cũng kết thúc bất thường. Sau đó, mainphương thức kết thúc và chương trình dừng lại.

Mục đích của những ngoại lệ này là gì? Chà, bạn có thể viết mã của riêng mình để nắm bắt các loại ngoại lệ cụ thể và viết logic của riêng bạn để xử lý các tình huống ngoại lệ.


2. Bắt ngoại lệ:try-catch

Java có một cơ chế bắt ngoại lệ cho phép bạn tạm dừng việc chấm dứt các phương thức bất thường này. Nó trông như thế này:

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

Cấu trúc này được gọi là một try-catchkhối.

Mã có thể xảy ra ngoại lệ được đặt trong dấu ngoặc nhọn, trước từ try.

Sau dấu ngoặc nhọn, chúng ta có catchtừ khóa và bên trong dấu ngoặc đơn là phần khai báo của một biến ngoại lệ . Tiếp theo là dấu ngoặc nhọn bọc mã sẽ được thực thi nếu xảy ra ngoại lệ của loại được chỉ định .

Nếu không có ngoại lệ nào được đưa ra trong quá trình thực thi " mã chính ", thì mã bên trong khối catch sẽ không được thực thi. Nếu một ngoại lệ xảy ra, thì nó sẽ xảy ra (nếu loại của ngoại lệ được ném ra giống với loại của biến trong ngoặc đơn).

Ví dụ:

Mã số Đầu ra bảng điều khiển
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. Nhiều catchkhối

Nhiều khối bắt

Về lý thuyết, tất cả các loại ngoại lệ có thể được đưa vào một khối mã. Một số bạn sẽ muốn giải quyết theo cách này, một số khác theo cách khác, và vẫn còn những trường hợp khác mà bạn sẽ quyết định không xử lý gì cả.

Các nhà phát triển Java đã quyết định giúp bạn và cho phép bạn viết không chỉ một mà là nhiều catchkhối sau trykhối đó.

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
}

Ví dụ:

Mã số Đầu ra bảng điều khiển
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. Thứ tự catchcác khối

Các ngoại lệ xảy ra trong một trykhối chỉ có thể được bắt bởi một catchkhối duy nhất. Bạn không thể có tình huống xử lý ngoại lệ trong đó mã từ nhiều catchkhối được thực thi.

Nhưng thứ tự của các khối quan trọng.

Bạn có thể gặp trường hợp một ngoại lệ có thể bị bắt bởi nhiều khối. Nếu đúng như vậy, thì ngoại lệ sẽ bị bắt bởi bất kỳ khối bắt nào đến trước (gần trykhối nhất).

Làm thế nào bạn có thể gặp tình huống nhiều khối bắt có thể bắt cùng một ngoại lệ?

Tất cả các ngoại lệ thuộc về một hệ thống phân cấp thừa kế duy nhất — xem sơ đồ.

phân cấp ngoại lệ

Một ArithmeticExceptionđối tượng có thể được gán cho một biến có kiểu ArithmeticExceptionhoặc bất kỳ lớp tổ tiên nào của nó: RuntimeException , ExceptionThrowable— xem sơ đồ.

Chúng ta sẽ nói nhiều hơn về các lớp kế thừa và tổ tiên ở Cấp độ 21.

Mã này sẽ biên dịch tốt:

Quyền lợi thừa kế:
ArithmeticException ae    = new ArithmeticException();
RuntimeException runtime  = new ArithmeticException();
Exception exception       = new ArithmeticException();
Throwable trwbl           = new ArithmeticException();

Vì vậy, bạn có thể bắt một ArithmeticExceptionvới bất kỳ khối nào trong 4 catchkhối trên.

Ví dụ 1:

Mã số Đầu ra bảng điều khiển
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

Trong ví dụ này, the ArithmeticExceptioncó thể bị bắt bởi cả the catch (Exception e)catch (ArithmeticException e)blocks. Nó sẽ bị bắt bởi khối gần trykhối nhất - khối đầu tiên catch.

Để tránh bất ngờ, tốt nhất là đặt catchcác khối có thể bắt gần như mọi ngoại lệ ở gần cuối danh sách catchcác khối.

Loại này Throwablethường có khả năng bắt mọi ngoại lệ có thể có trong Java . Nếu bạn đặt nó trong catchkhối đầu tiên, thì mã sẽ không được biên dịch, vì trình biên dịch biết rằng có những khối mã không thể truy cập được.