Xử lý ngoại lệ trong Java một cách chuyên nghiệp

6 min read

Xử lý ngoại lệ là một phần quan trọng trong phát triển phần mềm. Nó cho phép lập trình viên có thể xử lý đúng cách và khôi phục lại luồng hoạt động của chương trình từ lỗi không mong đợi hoặc những ngoại lệ đã lường trước.

Còn Java là một trong những ngôn ngữ lập trình phổ biến nhất, đã mang lại cho developer một cơ chế sử lý ngoại lệ một cách mạnh mẽ. Giúp tạo ra những phần mềm đáng tin cậy và có khả năng chịu lỗi tốt. Trong bài viết này chúng ta sẽ tìm hiểu một cách chi tiết bên trong thế giới của Java để xử lý Exception.

Bài viết có bao gồm một số đoạn mã demo giúp cho việc truyền đạt hiệu quả hơn.

Giới thiệu chung về xử lý ngoại lệ trong Java

Xử lý ngoại lệ là quá trình quản lý và phản ứng lại với một số điều kiện có thể xảy ra trong quá trình chương trình chạy. Trong Java ngoại lệ là một đối tượng đại diện cho những điều kiện làm chương trình bị gián đoạn. Khi một trường hợp ngoại lệ xảy ra thì một đối tượng sẽ được tạo ra.

Sau đó sẽ được thrown( tôi tạm dịch là ném) cho mục đích làn truyền ngoại này trong vào một ngăn xếp các lời gọi hàm cho đến khi được catch( tôi tạm dịch là tóm) lại và xử lý.

Ví dụ đời thực về Exception

Khi không có xử lý ngoại lệ

Giả sử rằng bạn đang xem một video trên Youtube. Đột nhiên tín hiệu internet của bạn mất kết nối hoặc model wifi không hoạt động. Trong trường hợp này bạn không thể tiếp tục xem video trên Youtube nữa. Sự gián đoạn này chính là exception.

Khi có xử lý ngoại lệ

Giả sử một người đang đi du lịch bằng ô tô từ Hà Nội đến Đà Nẵng. Sau khi đi được nửa chặng đường, thì lốp xe bị thủng. Đây là một “ngoại lệ” không mong muốn.

Người chủ xe đã tính đến tường hợp này và đã dự phòng một chiếc lốp để thay thế. Anh ta thay chiếc lốp thủng bằng chiếc lốp mới. Sau khi thay lốp, anh này lại tiếp tục cuộc hành trình còn lại. Việc thay lốp này còn gọi là xử lí ngoại lệ (exception handling).

Checked và Unchecked Exception

Có một câu hỏi mà thường được hỏi trong các lần phỏng vấn đó là trong Java thì có mấy loại Exception. Thì câu trả lời là 2 loại chính. Có một loại nữa (Errors) nhưng loại này nếu rơi vào thì đúng là hết cứu vì nó liên quan đến một số Excpetion như: OutOfMemoryError, VirtualMachineError, AssertionError. Nên trong bài viết này tôi chỉ đề cập đến 2 loại là: Checked Exception và Unchecked Exception

Checked exceptions

Đây là những ngoại lệ mà được kiểm tra bởi complier( được kiểm tra trong thời điểm code được biên dịch). Nghĩa là compiler sẽ đảm bảo những exception phải được xử lý đúng cách. Ví dụ về những exception thuộc loại này: IOException, SQLException, ClassNotFoundException, …

Unchecked exception

Còn được biết tới là runtime exception( xảy ra trong lúc chương trình chạy). Nhưng loại exception này không yêu cầu xử lý ngay lúc bạn viết code và không được kiểm tra bởi compiler. Những exception thuộc loại này có thể kể tới như: NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException, …

Các cách xử lý

Sử dụng khối try-catch

Khối try-catch là cấu trúc quạn trọng thường được sử dụng để xử lý ngoại lệ trong Java. Khối try bao gồm đoạn code có thể xảy ra một ngoại lệ, trong khi khối catch xỷ lý ngoại lệ nếu mà xuất hiện. Ví dụ:

try {
    // Code that may throw an exception
} catch (ExceptionType e) {
    // Exception handling code
}

Sử dụng nhiều khối catch và hệ thống phân cấp Exception

Java cho phép bắt nhiều ngoại lệ bằng cách sử dùng nhiều khối catch. Đây là hướng tiếp cận cho phép xử lý một cách cụ thể cho từng loại ngoại lệ khác nhau. Những khối catch sẽ so sánh một cách lần lượt và khối catch đầu tiên khớp thì đoạn code của khối catch đó sẽ được thực thi.

Hệ thống phân cấp các exception này cho phép bắt các loại ngoại lệ cấp thấp trước các ngoại lệ cấp cao để tránh sự dư thừa.

try {
    // Code that may throw an exception
} catch (IOException e) {
    // IOException handling code
} catch (SQLException e) {
    // SQLException handling code
} catch (Exception e) {
    // Generic exception handling code
}

Sử dụng khối finally

Khối finally có thể có hoặc không nhưng rất hữu ích khi cần “dọn dẹp” hay đoạn code mà bạn muốn nó luôn chạy cho dù có ngoại lệ xảy ra hay không. Khối finnally được đặt sau khối catch cuối cùng và được chạy dù kết quả thế nào chăng nữa.

try {
    // Code that may throw an exception
} catch (Exception e) {
    // Exception handling code
} finally {
    // Cleanup code
}

Chủ động ném ra một ngoại lệ

Bạn cũng có thể ném ra các ngoại lệ một cách rõ ràng bằng cách sử dụng throw. Đây là cơ chế cực kì hữu dụng khi mà một điều kiện đặc biệt được phát hiện và cần phải xử lý trong phương thức gọi. Hãy xem ví dụ sau:

public void validateAge(int age) throws IllegalArgumentException {
    if (age < 0) {
        throw new IllegalArgumentException("Age cannot be negative");
    }
}

Trong phương thức trên nếu age < 0 thì ta ném ra một ngoại lệ. Điều này nhằm thông báo cho hàm gọi phương thức validateAge rằng biến age đang mang giá trị không hợp lệ.

Sử dụng Exception do người dùng định nghĩa

Java cho phép chúng ta tạo ra những lớp ngoại lệ mới bằng cách kế thừa lớp Exception hoặc RuntimeException, … Những lớp ngoại lệ này có thể đóng gói các lỗi cụ thể và cung cấp thông tin có ý nghĩa hơn trong quá trình xử lý ngoại lệ

public class CustomException extends Exception {
    public CustomException(String message) {
        super(message);
    }
}

Sử dụng từ khóa throws

Khi một phương thức có thể sinh ra một ngoại lệ nhưng lại không muốn xử lý nó. Những ngoại lệ này có thể được khai báo ở đầu phương thức bằng cách sử dụng từ khóa throws(nhìn kĩ nhé throws).

Từ khóa này thông báo với phương thức cấp cao( là phương thức mà gọi phước thức có sử dụng từ khóa throws) rằng phương thức được gọi đó có thể sinh ra một ngoại lệ nào đó và cần phải xử lý hoặc nhả nó cho phương thức cấp cao hơn. Dưới đây là ví dụ:

public void readFile(String filePath) throws FileNotFoundException, IOException {
    // Code that may throw exceptions
}

Túm lại làm sao để xử lý Exception đúng cách?

  • Bắt những ngoại lệ ở những tầng phù hợp
  • Nên sử dụng thông báo lỗi có ý nghĩa để tiện cho việc debug sau này
  • Sử dụng từ khóa finnally cho việc dọn dẹp tài nguyên
  • Và cuối cùng hãy cận thận với hiệu năng hệ thống khi xử lý các ngoại lệ

Lời kết

Nói chung thì xử lý ngoại lệ là một kỹ năng cần thiêt cho một lập trình viện Java. Hiểu được các loại ngoại lệ, sử dụng try-catch một cách hiệu quả và biết khi nào tạo lớp ngoại lệ mới(custom exception). Bạn sẽ có thể viết nên những đoạn code dễ bảo trì và chịu lỗi tốt.

Cảm ơn bạn vì đã đọc đến đây. Nếu bài viết có sai sót hay cần chỉnh sửa ở đâu hãy cho tôi biết ở phần bình luận.

Chào thân ái và quyết thắng.

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *