CodeGym /Các khóa học /JAVA 25 SELF /Hệ phân cấp ngoại lệ trong Java

Hệ phân cấp ngoại lệ trong Java

JAVA 25 SELF
Mức độ , Bài học
Có sẵn

1. Lớp Throwable: gốc của mọi ngoại lệ

Bây giờ chúng ta sẽ phân tích chi tiết cách hệ thống ngoại lệ trong Java được tổ chức: Throwable là gì, ExceptionError khác nhau ra sao, và “đã kiểm tra” và “không kiểm tra” nghĩa là gì. Đây là nền tảng để xử lý lỗi một cách đúng đắn trong các chương trình của bạn.

Trong Java, tất cả ngoại lệ và lỗi đều là các đối tượng kế thừa từ lớp java.lang.Throwable.
Throwable — là “tổ tiên” của toàn bộ hệ phân cấp xử lý sự cố trong Java.

Sơ đồ khái quát:

Throwable
├── Exception
└── Error

Throwable — lớp cơ sở cho mọi thứ có thể được “ném” (throw) và “bắt” (catch) trong Java. Không thể sử dụng trực tiếp — nó đóng vai trò nền tảng cho các kiểu lỗi cụ thể hơn.

Exception — dành cho “lỗi bình thường”

Exception — lớp cơ sở cho các ngoại lệ có thể phát sinh trong chương trình và nên và cần được xử lý. Đây là các lỗi “trong công việc”: vấn đề với tệp, mạng, I/O, lỗi người dùng, v.v. Phần lớn các khối try-catch của bạn sẽ làm việc với các lớp con của Exception.

Ví dụ:

  • IOException — lỗi khi làm việc với tệp hoặc mạng.
  • SQLException — lỗi khi làm việc với cơ sở dữ liệu.
  • FileNotFoundException — không tìm thấy tệp.

Error — dành cho lỗi chí mạng của JVM

Error — lớp cơ sở cho các lỗi xảy ra ở mức máy ảo Java (JVM). Thường là các sự cố nghiêm trọng mà chương trình không thể và không nên xử lý. Nếu xuất hiện Error — nhiều khả năng ứng dụng không thể tiếp tục chạy.

Ví dụ:

  • OutOfMemoryError — hết bộ nhớ.
  • StackOverflowError — tràn stack (ví dụ do đệ quy vô hạn).
  • NoClassDefFoundError — không tìm thấy lớp cần thiết.

Quan trọng:
Bắt và xử lý Error — hầu như luôn là ý tưởng tệ. Đây không phải lỗi của chương trình bạn, mà là sự cố của môi trường thực thi.

2. Checked vs Unchecked exceptions: nghĩa là gì?

Trong Java, tất cả ngoại lệ được chia thành hai nhóm lớn:

Ngoại lệ đã kiểm tra (Checked)

Đó là gì? Các ngoại lệ mà trình biên dịch bắt buộc bạn phải xử lý hoặc khai báo ném tiếp.

Khi nào xảy ra? Thường liên quan đến tài nguyên bên ngoài: tệp, mạng, cơ sở dữ liệu, đầu vào của người dùng.

Xử lý thế nào? Hoặc bao bọc mã trong try-catch, hoặc thêm throws vào chữ ký phương thức.

Ví dụ: IOException, SQLException, FileNotFoundException

Ví dụ:

public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path); // có thể ném IOException
    // ...
}

Nếu không xử lý hoặc không khai báo ném tiếp — chương trình sẽ không biên dịch!

Ngoại lệ không kiểm tra (Unchecked)

Đó là gì? Các ngoại lệ không yêu cầu bắt buộc xử lý bởi trình biên dịch.

Khi nào xảy ra? Thường là lỗi trong logic chương trình: chia cho 0, vượt quá chỉ số mảng, truy cập null.

Xử lý thế nào? Có thể bắt nhưng không bắt buộc. Tốt hơn là phòng tránh bằng các kiểm tra hợp lệ.

Vị trí trong hệ phân cấp? Tất cả kế thừa từ RuntimeException.

Ví dụ: NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException, ArithmeticException

Ví dụ:

int[] arr = {1, 2, 3};
System.out.println(arr[10]); // ArrayIndexOutOfBoundsException

Trình biên dịch không bắt buộc bạn phải bắt ngoại lệ này — nhưng chương trình sẽ “sập” khi lỗi xảy ra.

3. Toàn bộ hệ phân cấp trong một hình

graph TD
    Throwable --> Error
    Throwable --> Exception
    
    Exception --> RuntimeException
    Exception --> CheckedExceptions["(các Checked Exception khác)"]
    
    Error --> OutOfMemoryError
    Error --> StackOverflowError
    
    RuntimeException --> NullPointerException
    RuntimeException --> IndexOutOfBoundsException
    RuntimeException --> IllegalArgumentException

    %% Kiểu dáng
    style Throwable fill:#ffa64d,color:#000
    style Exception fill:#ffa64d,color:#000
    style CheckedExceptions fill:#ffa64d,color:#000
    
    style Error fill:#ff4d4d,color:#fff
    style OutOfMemoryError fill:#ff4d4d,color:#fff
    style StackOverflowError fill:#ff4d4d,color:#fff
    
    style RuntimeException fill:#4dff88,color:#000
    style NullPointerException fill:#4dff88,color:#000
    style IndexOutOfBoundsException fill:#4dff88,color:#000
    style IllegalArgumentException fill:#4dff88,color:#000

Bảng: khác biệt chính

Nhóm Lớp cha Bắt buộc xử lý? Ví dụ
Checked Exception
Exception
IOException, SQLException
Unchecked
RuntimeException
Không
NullPointerException, IndexOutOfBoundsException
Error
Error
Không
OutOfMemoryError, StackOverflowError

4. Trông như thế nào trong mã?

Checked Exception: ví dụ với tệp

import java.io.*;

public class FileDemo {
    public static void main(String[] args) {
        try {
            FileReader reader = new FileReader("nofile.txt"); // FileNotFoundException (checked)
            int data = reader.read();
            System.out.println(data);
            reader.close();
        } catch (IOException e) {
            System.out.println("Lỗi khi làm việc với tệp: " + e.getMessage());
        }
    }
}

Trình biên dịch sẽ buộc bạn xử lý IOException!

Unchecked Exception: ví dụ chia cho 0

public class ExceptionDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        int c = a / b; // ArithmeticException (unchecked)
        System.out.println("Kết quả: " + c);
    }
}

Trình biên dịch không yêu cầu xử lý, nhưng chương trình sẽ sập.

5. Tại sao cần hệ phân cấp ngoại lệ?

  • Linh hoạt trong xử lý: Có thể bắt lỗi cụ thể (FileNotFoundException) hoặc cả một nhóm (IOException hoặc Exception).
  • Tái sử dụng mã: Có thể xử lý tập trung các lỗi cùng loại.
  • Sạch mã: Logic chính không bị lộn xộn bởi quá nhiều kiểm tra vụn vặt.

Ví dụ:

try {
    // mã nguy hiểm
} catch (FileNotFoundException e) {
    System.out.println("Không tìm thấy tệp!");
} catch (IOException e) {
    System.out.println("Lỗi nhập/xuất!");
} catch (Exception e) {
    System.out.println("Đã có lỗi xảy ra: " + e.getMessage());
}

6. Các lỗi thường gặp khi làm việc với ngoại lệ

Lỗi № 1: Bỏ qua ngoại lệ. Viết catch (Exception e) {} — không tốt! Bạn sẽ mất thông tin về nguyên nhân lỗi.

Lỗi № 2: Bắt quá nhiều. catch (Exception e) bắt mọi thứ, kể cả những gì bạn không ngờ tới. Tốt hơn hãy chỉ bắt những ngoại lệ mà bạn có thể xử lý.

Lỗi № 3: Bắt lỗi (Error). Không nên bắt Error nếu bạn không viết mã mức thấp. Đó là vấn đề của JVM, không phải của chương trình bạn.

Lỗi № 4: Không phân biệt checked và unchecked. Không phải mọi ngoại lệ đều như nhau! Checked yêu cầu xử lý (Exception), unchecked — không (RuntimeException và các lớp con).

Lỗi № 5: Không thêm thông tin vào ngoại lệ. Nếu bạn tạo ngoại lệ của riêng mình — hãy luôn thêm thông điệp có tính thông tin.

1
Nhiệm vụ
JAVA 25 SELF, mức độ, bài học
Đã khóa
Giải mã bí ẩn ngoại lệ: Hệ phân cấp lớp cha
Giải mã bí ẩn ngoại lệ: Hệ phân cấp lớp cha
1
Nhiệm vụ
JAVA 25 SELF, mức độ, bài học
Đã khóa
Ai là kẻ chủ? Sự khác biệt giữa ngoại lệ và lỗi
Ai là kẻ chủ? Sự khác biệt giữa ngoại lệ và lỗi
1
Nhiệm vụ
JAVA 25 SELF, mức độ, bài học
Đã khóa
Hệ thống cảnh báo: Mối đe dọa được kiểm tra và không được kiểm tra
Hệ thống cảnh báo: Mối đe dọa được kiểm tra và không được kiểm tra
1
Nhiệm vụ
JAVA 25 SELF, mức độ, bài học
Đã khóa
Robot thủ thư và "kế hoạch cứu hộ"
Robot thủ thư và "kế hoạch cứu hộ"
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION