Java xử lý lỗi bằng try/catch/finally, và một cách độc đáo phân biệt exception checked (phải khai báo hoặc xử lý) với exception unchecked (runtime, không bị ép buộc). Hiểu sự phân biệt này là trung tâm của việc xử lý lỗi trong Java.
Java xử lý lỗi bằng try/catch/finally, và một cách độc đáo phân biệt exception checked (phải khai báo hoặc xử lý) với exception unchecked (runtime, không bị ép buộc). Hiểu sự phân biệt này là trung tâm của việc xử lý lỗi trong Java.
try {
FileReader f = new FileReader("file.txt"); // có thể ném IOException
// ... sử dụng nó ...
} catch (FileNotFoundException e) {
System.out.println("not found: " + e.getMessage()); // cụ thể đặt trước
} catch (IOException e) {
System.out.println("io error"); // tổng quát hơn đặt sau
} finally {
System.out.println("always runs — cleanup"); // luôn chạy dù thế nào
}
finally luôn được thực thi (dọn dẹp), kể cả khi có exception bị ném ra hoặc có return.
Throwable
├── Error — vấn đề nghiêm trọng của JVM (OutOfMemoryError) — đừng catch
└── Exception
├── RuntimeException → UNCHECKED (compiler không ép buộc)
│ NullPointerException, IllegalArgumentException, IndexOutOfBounds...
└── (các Exception khác) → CHECKED (compiler ép buộc xử lý)
IOException, SQLException...
// PHẢI hoặc catch nó hoặc khai báo `throws` — compiler không cho bỏ qua
public void readFile() throws IOException { // khai báo nó
Files.readAllLines(Paths.get("file.txt")); // ném checked IOException
}
Exception checked (IOException, SQLException) biểu diễn các tình huống có thể phục hồi, được dự kiến (thiếu file, lỗi mạng). Compiler bắt buộc bạn xử lý hoặc khai báo chúng — khiến việc xử lý lỗi từ bên ngoài trở nên rõ ràng.
// KHÔNG bắt buộc khai báo hay catch — thường chỉ ra LỖI LẬP TRÌNH
String s = null;
s.length(); // NullPointerException (unchecked)
int x = arr[10]; // ArrayIndexOutOfBoundsException (unchecked)
Integer.parseInt("abc"); // NumberFormatException (unchecked)
Unchecked (các subclass của RuntimeException) thường báo hiệu lỗi lập trình — bạn sửa bug chứ không catch ở khắp nơi. Compiler không ép buộc xử lý.
// resource implement AutoCloseable sẽ được đóng tự động
try (FileReader f = new FileReader("file.txt")) {
// dùng f
} // f.close() được gọi tự động, kể cả khi có exception — không cần finally
✓ Catch các exception cụ thể, không catch Exception trần
✓ Dùng try-with-resources cho file/connection (tự động đóng)
✓ Đừng nuốt exception âm thầm (catch block rỗng)
✓ Ném exception có ý nghĩa; đưa context vào trong message
✓ Custom exception kế thừa Exception (checked) hoặc RuntimeException (unchecked)
Xử lý lỗi vững chắc là thiết yếu, và sự phân biệt checked/unchecked của Java là một đặc trưng (và gây tranh luận) đáng để hiểu sâu.
Checked exception buộc xử lý rõ ràng các lỗi bên ngoài được dự kiến (I/O, DB) — thúc đẩy độ tin cậy nhưng đôi khi bị phê phán là dài dòng; unchecked exception biểu diễn các bug cần sửa thay vì catch thường xuyên.
Biết hệ phân cấp, khi nào áp dụng mỗi loại, ngữ nghĩa try/catch/finally, và try-with-resources hiện đại để tự động dọn dẹp là nền tảng để viết Java đúng đắn, đáng tin cậy — và để thiết kế exception của riêng bạn cho phù hợp.
Sự phân biệt này định hình cách các API Java được thiết kế và là chủ đề thường gặp trong phỏng vấn và code-review.