Checked vs Unchecked Exception
Vấn đề
Phần tiêu đề “Vấn đề”Java có hai nhóm exception hoàn toàn khác nhau về cách trình biên dịch xử lý, và việc nhầm lẫn hai nhóm này khiến lập trình viên mới hay bối rối khi gặp lỗi biên dịch khó hiểu hoặc quên xử lý lỗi quan trọng:
import java.io.FileReader;import java.io.IOException;
FileReader reader = new FileReader("data.txt"); // LỖI BIÊN DỊCH! Chưa xử lý IOExceptionint[] numbers = {1, 2, 3};System.out.println(numbers[10]); // BIÊN DỊCH OK, nhưng ném ArrayIndexOutOfBoundsException lúc chạyVì sao dòng đầu bắt buộc phải xử lý lỗi ngay khi biên dịch, còn dòng sau thì không?
Vì sao xảy ra?
Phần tiêu đề “Vì sao xảy ra?”Java phân loại exception thành hai nhóm:
Checked exception: kế thừa từ Exception nhưng không kế thừa từ RuntimeException (ví dụ IOException, SQLException). Trình biên dịch bắt buộc bạn phải xử lý (try/catch) hoặc khai báo throws trong chữ ký phương thức - đại diện cho các lỗi có thể lường trước và nên xử lý (file không tồn tại, kết nối mạng thất bại…).
Unchecked exception: kế thừa từ RuntimeException (ví dụ NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException, IllegalArgumentException). Trình biên dịch không bắt buộc xử lý - thường đại diện cho lỗi logic của lập trình viên mà lý tưởng nhất là nên sửa code để tránh xảy ra, thay vì bắt và bỏ qua.
import java.io.FileReader;import java.io.IOException;
// Cách 1: xử lý bằng try/catchtry { FileReader reader = new FileReader("data.txt");} catch (IOException e) { System.out.println("Không đọc được file: " + e.getMessage());}
// Cách 2: khai báo throws, đẩy trách nhiệm xử lý cho nơi gọi phương thức nàystatic void readFile() throws IOException { FileReader reader = new FileReader("data.txt");}Cây phân cấp (rút gọn)
Phần tiêu đề “Cây phân cấp (rút gọn)”Throwable├── Error (lỗi nghiêm trọng cấp hệ thống, không nên tự bắt - ví dụ OutOfMemoryError)└── Exception ├── RuntimeException (UNCHECKED - NullPointerException, ArithmeticException,...) └── (các Exception khác) (CHECKED - IOException, SQLException,...)Giải pháp / Cách dùng đúng
Phần tiêu đề “Giải pháp / Cách dùng đúng”- Với checked exception: xử lý thật sự có ý nghĩa (log, thử lại, thông báo người dùng) - tránh
catch (Exception e) {}bắt rồi bỏ qua trống rỗng, che giấu lỗi thật sự - Với unchecked exception: ưu tiên sửa nguyên nhân gốc (kiểm tra
null, kiểm tra chỉ số hợp lệ trước) thay vì bắt và bỏ qua mọi lúc mọi nơi - Có thể tự định nghĩa exception riêng bằng cách kế thừa
Exception(checked) hoặcRuntimeException(unchecked) tùy vào việc có muốn bắt buộc nơi gọi phải xử lý hay không
Tóm tắt
Phần tiêu đề “Tóm tắt”Checked exception (không kế thừa
RuntimeException): bắt buộc xử lý ngay lúc biên dịch (try/catchhoặcthrows). Unchecked exception (kế thừaRuntimeException): không bắt buộc xử lý, thường là dấu hiệu của lỗi logic nên sửa trong code thay vì bắt và bỏ qua.