JavaRush /Blog Java /Random-VI /Ngoại lệ: đã chọn, không được chọn và của riêng bạn

Ngoại lệ: đã chọn, không được chọn và của riêng bạn

Xuất bản trong nhóm
Xin chào! Trong bài giảng trước, chúng ta đã làm quen với khía cạnh ngoại lệ của ngôn ngữ Java và xem các ví dụ về cách làm việc với chúng. Hôm nay chúng ta sẽ xem xét sâu hơn về cấu trúc của chúng và cũng học cách viết các ngoại lệ của riêng mình :)

Các loại ngoại lệ

Như chúng tôi đã nói, có rất nhiều lớp ngoại lệ trong Java, gần 400! Nhưng chúng đều được chia thành các nhóm nên khá dễ nhớ. Nó trông như thế này: Ngoại lệ: đã chọn, không được chọn và của riêng bạn - 2Tất cả các ngoại lệ đều có một lớp tổ tiên chung Throwable. Hai nhóm lớn đến từ nó - ngoại lệ (Ngoại lệ) và lỗi (Lỗi). Lỗi là lỗi nghiêm trọng trong quá trình thực thi chương trình liên quan đến hoạt động của máy ảo Java. Trong hầu hết các trường hợp, Lỗi không cần phải xử lý vì nó chỉ ra một số lỗi nghiêm trọng trong mã. Các lỗi nổi tiếng nhất: StackOverflowError- ví dụ, xảy ra khi một phương thức gọi chính nó không ngừng và OutOfMemoryError- xảy ra khi không có đủ bộ nhớ để tạo đối tượng mới. Như bạn có thể thấy, trong những tình huống này, hầu hết không có gì đặc biệt để xử lý - mã chỉ được viết sai và cần phải được làm lại. Trên thực tế, các ngoại lệ là các ngoại lệ: một tình huống ngoại lệ, ngoài kế hoạch xảy ra trong khi chương trình đang chạy. Đây không phải là những lỗi nghiêm trọng như Lỗi nhưng chúng cần được chúng ta chú ý. Tất cả các ngoại lệ được chia thành 2 loại - đã chọn ( đã chọn ) và không được chọn ( không được chọn ). Ngoại lệ: đã chọn, không được chọn và của riêng bạn - 3Tất cả các ngoại lệ được kiểm tra đều đến từ Exception. "Có thể kiểm chứng" nghĩa là gì? Chúng tôi đã đề cập một phần điều này trong bài giảng trước : “...trình biên dịch Java biết về các ngoại lệ phổ biến nhất và biết chúng có thể xảy ra trong những tình huống nào.” Ví dụ, anh ta biết rằng nếu một lập trình viên đọc dữ liệu từ một tệp trong mã, thì có thể dễ dàng phát sinh tình huống tệp đó không tồn tại. Và có rất nhiều tình huống như vậy mà anh ấy có thể đoán trước được. Do đó, trình biên dịch sẽ kiểm tra trước mã của chúng tôi để tìm các trường hợp ngoại lệ có thể xảy ra. Nếu tìm thấy chúng, nó sẽ không biên dịch mã cho đến khi chúng tôi xử lý chúng hoặc chuyển tiếp chúng lên trên cùng. Loại ngoại lệ thứ hai là “không được kiểm tra”. Họ đến từ lớp học RuntimeException. Chúng khác với những gì đang được thử nghiệm như thế nào? Có vẻ như cũng có một loạt các lớp khác nhau xuất phát RuntimeExceptionvà mô tả các ngoại lệ thời gian chạy cụ thể. Sự khác biệt là trình biên dịch không mong đợi những lỗi này. Có vẻ như anh ấy đang nói: “Tại thời điểm viết mã, tôi không tìm thấy điều gì đáng ngờ, nhưng đã xảy ra sự cố khi nó đang hoạt động. Rõ ràng là có lỗi trong mã!” Và thực sự là như vậy. Các ngoại lệ không được kiểm tra thường là kết quả của lỗi lập trình viên. Và trình biên dịch rõ ràng không thể cung cấp tất cả các tình huống không chính xác có thể xảy ra mà mọi người có thể tự tạo ra :) Do đó, nó sẽ không kiểm tra việc xử lý các trường hợp ngoại lệ như vậy trong mã của chúng tôi. Bạn đã gặp phải một số trường hợp ngoại lệ không được kiểm tra:
  • ArithmeticExceptionxảy ra khi chia cho số 0
  • ArrayIndexOutOfBoundsExceptionXảy ra khi cố gắng truy cập vào một ô bên ngoài mảng.
Tất nhiên, về mặt lý thuyết, những người tạo ra Java có thể đã đưa ra cách xử lý bắt buộc đối với những trường hợp ngoại lệ như vậy, nhưng khi đó mã sẽ trở thành gì? Với bất kỳ thao tác chia số nào, bạn sẽ phải viết một câu thử để kiểm tra xem liệu bạn có vô tình chia cho 0 không? Bất cứ khi nào truy cập vào một mảng, bạn sẽ phải viết một bản thử bắt để kiểm tra xem bạn có vượt quá các giới hạn này hay không. Bất kỳ mã nào được viết sẽ là spaghetti và hoàn toàn không thể đọc được. Điều hợp lý là ý tưởng này đã bị bỏ rơi. Do đó, các ngoại lệ không được kiểm tra không cần phải được xử lý trong các khối try-catch hoặc được đưa lên trên cùng, mặc dù điều này là có thể về mặt kỹ thuật, như với Error.

Cách ném ngoại lệ của bạn

Tất nhiên, những người tạo ra Java không thể cung cấp tất cả các tình huống đặc biệt có thể phát sinh trong chương trình. Có quá nhiều chương trình trên thế giới và chúng quá khác nhau. Nhưng không sao cả, vì bạn có thể tạo ngoại lệ của riêng mình nếu cần. Điều này được thực hiện rất dễ dàng. Tất cả bạn phải làm là tạo lớp học của riêng bạn. Tên của nó phải kết thúc bằng “Exception”. Trình biên dịch không cần điều này, nhưng các lập trình viên đọc mã của bạn sẽ hiểu ngay rằng đây là một lớp ngoại lệ. Ngoài ra, bạn cần chỉ rõ lớp đó đến từ lớp Exception. Điều này đã cần thiết cho trình biên dịch và hoạt động chính xác. Ví dụ: chúng ta có lớp Dog - Dog. Chúng ta có thể dắt chó đi dạo bằng cách sử dụng walk(). Nhưng trước đó, chúng ta cần kiểm tra xem thú cưng của mình có đeo vòng cổ, dây xích và rọ mõm hay không. Nếu thiếu bất kỳ thứ nào trong số này, chúng tôi sẽ đưa ra ngoại lệ của riêng mình DogIsNotReadyException. Mã của nó sẽ trông như thế này:
public class DogIsNotReadyException extends Exception {

   public DogIsNotReadyException(String message) {
       super(message);
   }
}
Để chỉ ra rằng một lớp là một ngoại lệ, bạn cần viết mở rộng Ngoại lệ sau tên lớp: điều này có nghĩa là “lớp bắt nguồn từ ngoại lệ của lớp”. Trong hàm tạo, chúng ta sẽ chỉ gọi hàm tạo của lớp Exceptionbằng một dòng message- nó sẽ hiển thị cho người dùng một thông báo từ hệ thống mô tả lỗi đã xảy ra. Đây là những gì nó sẽ trông giống như trong mã lớp của chúng tôi:
public class Dog {

   String name;
   boolean isCollarPutOn;
   boolean isLeashPutOn;
   boolean isMuzzlePutOn;

   public Dog(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

   }

   public void putCollar() {

       System.out.println("The collar is on!");
       this.isCollarPutOn = true;
   }

   public void putLeash() {

       System.out.println("The leash is on!");
       this.isLeashPutOn = true;
   }

   public void putMuzzle() {
       System.out.println("The muzzle is on!");
       this.isMuzzlePutOn = true;
   }

   public void walk() throws DogIsNotReadyException {

   System.out.println("Let's go for a walk!");
   if (isCollarPutOn && isLeashPutOn && isMuzzlePutOn) {
       System.out.println("Hurrah, let's go for a walk!" + name + " I am glad!");
   } else {
       throw new DogIsNotReadyException("Dog " + name + "not ready for a walk! Check your gear!");
   }
 }

}
Bây giờ phương thức của chúng tôi walk()đưa ra một ngoại lệ DogIsNotReadyException. Điều này được thực hiện bằng cách sử dụng từ khóa throw. Như chúng tôi đã nói trước đó, một ngoại lệ là một đối tượng. Do đó, trong phương pháp của chúng tôi, khi một tình huống đặc biệt xảy ra - con chó bị thiếu thứ gì đó - chúng tôi tạo một đối tượng lớp mới DogIsNotReadyExceptionvà ném nó vào chương trình bằng cách sử dụng từ throw. walk()Chúng tôi thêm các lần ném vào chữ ký phương thức DogIsNotReadyException. Nói cách khác, trình biên dịch hiện biết rằng lệnh gọi phương thức walk()có thể dẫn đến một ngoại lệ. Vì vậy, khi chúng ta gọi nó ở đâu đó trong chương trình, ngoại lệ sẽ cần được xử lý. Hãy thử thực hiện điều này theo phương thức main():
public static void main(String[] args) {

   Dog dog = new Dog("Mukhtar");
   dog.putCollar();
   dog.putMuzzle();
   dog.walk();//Unhandled exception: DogIsNotReadyException
}
Không biên dịch, ngoại lệ không được xử lý! Hãy bọc mã của chúng tôi trong một khối try-catchđể xử lý ngoại lệ:
public static void main(String[] args) {

   Dog dog = new Dog("Mukhtar");
   dog.putCollar();
   dog.putMuzzle();
   try {
       dog.walk();
   } catch (DogIsNotReadyException e) {
       System.out.println(e.getMessage());
       System.out.println("Checking equipment! Is the collar on?" + dog.isCollarPutOn + "\r\n Is the leash on?"
       + dog.isLeashPutOn + "\r\n Are you wearing a muzzle?" + dog.isMuzzlePutOn);
   }
}
Bây giờ hãy nhìn vào đầu ra của giao diện điều khiển:

Ошейник надет! 
Намордник надет! 
Собираемся на прогулку! 
Собака Мухтар не готова к прогулке! Проверьте экипировку! 
Проверяем снаряжение! Ошейник надет? true
Поводок надет? false 
Намордник надет? true
Hãy xem đầu ra của bảng điều khiển đã trở nên giàu thông tin hơn biết bao! Chúng tôi thấy từng bước diễn ra trong chương trình; Chúng tôi biết lỗi xảy ra ở đâu và ngay lập tức nhận thấy chính xác con chó của chúng tôi đang thiếu gì :) Đây là cách chúng tôi tạo ra các ngoại lệ của riêng mình. Như bạn có thể thấy, không có gì phức tạp. Và mặc dù các nhà phát triển Java không buồn thêm một ngoại lệ đặc biệt vào ngôn ngữ của họ đối với những con chó được trang bị không đúng cách, nhưng chúng tôi đã sửa lỗi giám sát của họ :)
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION