CodeGym /Blog Java /Ngẫu nhiên /Ngoại lệ: đã chọn, chưa chọn và tùy chỉnh

Ngoại lệ: đã chọn, chưa chọn và tùy chỉnh

Xuất bản trong nhóm
CHÀO! Trong bài học trước, chúng ta đã làm quen với các ngoại lệ trong 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 các ngoại lệ và tìm hiểu 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 trước đây, có rất nhiều ngoại lệ trong Java, gần 400! Nhưng tất cả chúng đều được chia thành các nhóm nên khá dễ nhớ chúng. Nó trông như thế này: Ngoại lệ: đã chọn, chưa chọn và tùy chỉnh - 2 Tất cả các ngoại lệ đều có một tổ tiên chung trong Throwablelớp. Hai nhóm chính bắt nguồn từ nó: ngoại lệ ( Exception ) và lỗi ( Error ). Lỗi - Đây là lỗi thời gian chạy nghiêm trọng 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 xử lý vì nó chỉ ra một số lỗi nghiêm trọng trong mã. Nổi tiếng nhất trong số này là StackOverflowError (ví dụ, điều này xảy ra khi một phương thức gọi chính nó liên tục) và OutOfMemoryError(điều này 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, thường hoàn toàn không có gì để xử lý trong thời gian chạy: đơn giản là mã được viết sai và cần được làm lại. Ngoại lệ - Điều này đại diện cho một ngoại lệ: một tình huống ngoại lệ, ngoài ý muốn xảy ra trong khi chương trình đang chạy. Chúng không nghiêm trọng như Lỗi, nhưng chúng vẫn cần sự chú ý của chúng tôi. Tất cả các ngoại lệ được chia thành 2 loại: được kiểm trakhông được kiểm tra . Ngoại lệ: đã chọn, chưa chọn và tùy chỉnh - 3 Tất cả các ngoại lệ được kiểm tra đều bắt nguồn từ Exceptionlớp. "Đã kiểm tra" có nghĩa là gì? Chúng ta đã đề cập đến điều này trong bài học trước: "Do đó, trình biên dịch Java biết các ngoại lệ phổ biến nhất và các tình huống mà chúng có thể xảy ra." Ví dụ, nó biết rằng nếu mã đọc dữ liệu từ một tệp, thì tệp đó có thể dễ dàng không tồn tại. Và có rất nhiều tình huống như vậy (mà nó có thể suy ra). Theo đó, trình biên dịch sẽ kiểm tra trước mã của chúng tôi để biết sự hiện diện của các ngoại lệ tiềm ẩn này. Nếu nó 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 ném lại chúng. Loại ngoại lệ thứ hai là "không được kiểm tra". Chúng có nguồn gốc từ RuntimeExceptionlớp. Chúng khác với ngoại lệ được kiểm tra như thế nào? Có vẻ như cũng có rất nhiều lớp khác nhau bắt nguồn từRuntimeException(mô tả các ngoại lệ thời gian chạy). Sự khác biệt là trình biên dịch không lường trước được những lỗi này. Có vẻ như nó nói, "Khi mã được viết, tôi không thấy có gì đáng ngờ, nhưng đã xảy ra sự cố khi mã đang chạy. Rõ ràng, có lỗi trong mã!" Và thực sự điều này là đúng. 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ể thấy trước mọi tình huống xấu có thể xảy ra mà mọi người có thể tạo ra bằng chính đôi tay của họ. :) Do đó, nó không kiểm tra xem các ngoại lệ như vậy có được xử lý trong mã của chúng tôi hay không. Bạn đã gặp phải một số trường hợp ngoại lệ không được kiểm soát:
  • Một ArithmeticException xảy ra khi chia cho số không
  • Một ArrayIndexOutOfBoundsException xảy ra khi bạn cố truy cập vào một vị trí bên ngoài mảng.
Tất nhiên, bạn có thể tưởng tượng rằng những người tạo ra Java có thể đã đưa ra cách xử lý ngoại lệ bắt buộc, nhưng trong trường hợp này, mã sẽ quá phức tạp. Đối với bất kỳ phép chia nào, bạn có phải viết một try-catchkhối để kiểm tra xem bạn có vô tình chia cho 0 không? Bất cứ khi nào bạn truy cập một mảng, bạn sẽ phải viết một try-catchkhối để kiểm tra xem chỉ mục của bạn có vượt quá giới hạn hay không. Mọi thứ sẽ là mã spaghetti và sẽ hoàn toàn không thể đọc được. Có nghĩa là ý tưởng này đã bị loại bỏ. Do đó, các trường hợp ngoại lệ không được kiểm tra không cần phải được xử lý theo try-catchkhối hoặc ném lại (mặc dù điều này là có thể về mặt kỹ thuật, như với Lỗi).

Làm thế nào để ném ngoại lệ của riêng bạn

Tất nhiên, những người tạo ra Java không thể thấy trước mọi tình huống ngoại lệ 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á đa dạng. Nhưng điều này không có gì đáng lo ngại vì bạn có thể tạo ngoại lệ của riêng mình nếu cần. Điều này rất dễ thực hiện. Tất cả bạn phải làm là tạo lớp học của riêng bạn. Bạn nên chắc chắn rằng tên của nó kết thúc bằng "Ngoại lệ". Trình biên dịch không yêu cầu điều này, nhưng những lập trình viên khác đọc mã của bạn sẽ hiểu ngay rằng đó là một lớp ngoại lệ. Ngoài ra, chỉ ra rằng lớp được kế thừa từ Exceptionlớp (trình biên dịch yêu cầu điều này). Ví dụ, giả sử chúng ta có một Doglớp. Chúng ta có thể dắt chó đi dạo bằng cách sử dụngwalk()phương pháp. Nhưng trước khi làm điều đó, 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ỳ thiết bị 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ó trông như thế này:

public class DogIsNotReadyException extends Exception {

   public DogIsNotReadyException(String message) {
       super(message);
   }
}
Để chỉ ra rằng lớp là một ngoại lệ, bạn cần viết " extends Exception " sau tên lớp (điều này có nghĩa là "lớp được dẫn xuất từ ​​lớp Exception"). Trong hàm tạo, chúng ta chỉ cần gọi Exceptionhàm tạo của lớp bằng thông báo Chuỗi (nếu ngoại lệ xảy ra, chúng tôi sẽ hiển thị thông báo, mô tả lỗi, cho người dùng). Đây là giao diện của nó 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("We're getting ready for a walk!");
   if (isCollarPutOn && isLeashPutOn && isMuzzlePutOn) {
       System.out.println("Hooray, let's go for a walk! " + name + " is very happy!");
   } else {
       throw new DogIsNotReadyException(name + " is not ready for a walk! Check the gear!");
   }
 }

}
Bây giờ, walk()phương thức của chúng ta ném ra một DogIsNotReadyException . Điều này được thực hiện với từ khóa ném. Như chúng tôi đã nói trước đó, một ngoại lệ là một đối tượng. Vì vậy, khi một ngoại lệ xảy ra (con chó bị thiếu thứ gì đó) trong phương thức của chúng ta, chúng ta tạo một DogIsNotReadyExceptionđối tượng mới và ném nó bằng từ khóa ném. Chúng tôi thêm " throws DogIsNotReadyException " vào phần khai báo phương thức. Nói cách khác, bây giờ trình biên dịch biết rằng việc gọi walk()phương thức có thể trở thành một tình huống ngoại lệ. Theo đó, ngoại lệ này phải được xử lý nếu chúng ta gọi phương thức này ở đâu đó trong chương trình của mình. Hãy thử làm điều này theo main()phương pháp:

public static void main(String[] args) {
  
   Dog dog = new Dog("Buddy");
   dog.putCollar();
   dog.putMuzzle();
   dog.walk();// Unhandled exception: DogIsNotReadyException
}
Điều này sẽ không được biên dịch. Ngoại lệ không được xử lý! Chúng tôi bọc mã của mình trong một try-catchkhối để xử lý ngoại lệ:

public static void main(String[] args) {

   Dog dog = new Dog("Buddy");
   dog.putCollar();
   dog.putMuzzle();
   try {
       dog.walk();
   } catch (DogIsNotReadyException e) {
       System.out.println(e.getMessage());
       System.out.println("Checking the gear! Is the collar on? " + dog.isCollarPutOn + "\r\n Is the leash on? "
       + dog.isLeashPutOn + "\r\n Is the muzzle on? " + dog.isMuzzlePutOn);
   }
}
Bây giờ hãy nhìn vào đầu ra của bàn điều khiển: Cổ áo đã bật! Mõm đã bật! Chúng tôi đang chuẩn bị đi dạo! Buddy chưa sẵn sàng để đi dạo! Kiểm tra thiết bị! Kiểm tra thiết bị! Là cổ áo trên? đúng Là dây xích trên? sai Là mõm trên? true Hãy xem đầu ra của bảng điều khiển có nhiều thông tin hơn như thế nào! Chúng tôi thấy mọi bước được thực hiện trong chương trình; chúng tôi thấy lỗi xảy ra ở đâu và chúng tôi cũng có thể thấy ngay chính xác con chó của mình đang thiếu gì. :) Và đó là cách bạn tạo 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ề nó. Và mặc dù những người tạo ra Java không thèm đưa vào ngôn ngữ này một ngoại lệ đặc biệt dành cho những chú chó được trang bị kém, chúng tôi đã khắc phục 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