Bỏ qua để đến nội dung

Xử lý ngoại lệ (Exception Handling)

Ngoại lệ (exception) là một sự kiện bất thường xảy ra lúc chương trình đang chạy, làm gián đoạn luồng thực thi bình thường - ví dụ chia cho 0, truy cập chỉ số mảng ngoài phạm vi, hay chuyển đổi chuỗi không hợp lệ sang số:

int[] numbers = {1, 2, 3};
System.out.println(numbers[5]); // ArrayIndexOutOfBoundsException - chương trình dừng đột ngột nếu không xử lý
try {
int[] numbers = {1, 2, 3};
System.out.println(numbers[5]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Lỗi: truy cập chỉ số ngoài phạm vi - " + e.getMessage());
}
System.out.println("Chương trình vẫn tiếp tục chạy"); // vẫn chạy được vì lỗi đã được "bắt"
try {
Scanner scanner = new Scanner(System.in);
int number = Integer.parseInt(scanner.nextLine());
int result = 100 / number;
System.out.println(result);
} catch (NumberFormatException e) {
System.out.println("Dữ liệu nhập không phải là số!");
} catch (ArithmeticException e) {
System.out.println("Không thể chia cho 0!");
}

Có thể gộp nhiều loại ngoại lệ vào một catch bằng | nếu xử lý giống nhau:

catch (NumberFormatException | ArithmeticException e) {
System.out.println("Có lỗi xảy ra: " + e.getMessage());
}

Khối finally luôn luôn chạy, dù try thành công, ném ngoại lệ, hay thậm chí có return bên trong try/catch - thường dùng để giải phóng tài nguyên (đóng file, đóng kết nối…):

Scanner scanner = new Scanner(System.in);
try {
int number = scanner.nextInt();
System.out.println(100 / number);
} catch (ArithmeticException e) {
System.out.println("Lỗi chia cho 0!");
} finally {
scanner.close(); // luôn chạy, đảm bảo tài nguyên được giải phóng
System.out.println("Đã đóng scanner");
}

Xem chi tiết các trường hợp đặc biệt của finally ở trang “finally luôn chạy” trong mục What the Java!.

5. Checked vs Unchecked exception (giới thiệu nhanh)

Phần tiêu đề “5. Checked vs Unchecked exception (giới thiệu nhanh)”

Java phân biệt hai nhóm ngoại lệ:

  • Checked exception: trình biên dịch bắt buộc phải xử lý (try/catch) hoặc khai báo throws - ví dụ IOException
  • Unchecked exception (RuntimeException và các lớp con): không bắt buộc xử lý - ví dụ NullPointerException, ArithmeticException

Chi tiết về sự khác biệt này ở trang “Checked vs Unchecked Exception” trong mục What the Java!.

static void checkAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("Tuổi không thể âm: " + age);
}
System.out.println("Tuổi hợp lệ: " + age);
}
  • try chứa code có thể gây lỗi, catch bắt và xử lý ngoại lệ theo từng loại
  • finally luôn chạy - dùng để dọn dẹp tài nguyên
  • throw để tự ném một ngoại lệ khi phát hiện điều kiện không hợp lệ
  • Java phân biệt checked exception (bắt buộc xử lý) và unchecked exception (không bắt buộc)