Exception
Nội dung bài · 6 mục
Người dùng gõ "abc" vào ô số lượng, file cấu hình bị xoá, mạng rớt giữa chừng. Những lỗi này chỉ xuất hiện lúc chạy. Không xử lý thì chương trình dừng ngay. Bài này hướng dẫn cách bắt lỗi và cách tự báo lỗi.
Khái niệm
💥 Exception: object mô tả một lỗi xảy ra lúc chạy, làm chương trình dừng nếu không ai bắt.
🧯 try/catch: cặp khối chạy code trong try, và nếu có exception thì xử lý nó trong catch.
🚨 throw: câu lệnh ném ra một exception, thường viết kèm new để tạo exception đó.
Ví dụ
// Main.java
void main() {
String input = "abc";
try {
int quantity = Integer.parseInt(input);
System.out.println("Số lượng: " + quantity);
} catch (NumberFormatException e) {
System.out.println("Vui lòng nhập một con số");
}
}Integer.parseInt("abc")némNumberFormatException. Code còn lại trongtrybị bỏ qua, chương trình nhảy sangcatch.catch (NumberFormatException e)chỉ bắt đúng loại lỗi đó, và đặt tênecho exception bắt được. Loại khác vẫn làm chương trình dừng.- Có thể thêm khối
finallysaucatch. Code trongfinallyluôn chạy, dù có lỗi hay không.
Tên exception hay gặp: NumberFormatException (sai định dạng số),
NullPointerException (dùng biến đang là null),
IllegalArgumentException (tham số không hợp lệ), IllegalStateException
(thao tác không hợp lệ lúc đó).
Các exception trên không bắt buộc phải catch. Riêng một số loại như
IOException (lỗi đọc ghi file) là checked exception: nơi gọi phải catch
hoặc ghi throws IOException ở khai báo method, nếu không sẽ lỗi compile.
Tự ném exception
Khi method nhận dữ liệu không hợp lệ, hãy throw để báo ngay thay vì âm thầm
chạy sai:
// Main.java
void main() {
System.out.println(total(5000, 2)); // 10000
}
long total(long price, int quantity) {
if (quantity <= 0) {
throw new IllegalArgumentException(
"Số lượng phải lớn hơn 0");
}
return price * quantity;
}Thử ngay
Chép chương trình ở trên vào Main.java, thay dòng gọi total trong
main bằng:
try {
System.out.println("A");
System.out.println(total(5000, 0));
System.out.println("B");
} catch (IllegalArgumentException e) {
System.out.println("Lỗi: " + e.getMessage());
} finally {
System.out.println("C");
}Đoán trước khi chạy: chữ "B" có được in không?
Xem kết quả
A
Lỗi: Số lượng phải lớn hơn 0
C"B" không được in. Exception xảy ra ở dòng giữa, nên phần còn lại của try bị
bỏ qua.
e.getMessage() là nội dung đã truyền lúc throw. finally vẫn chạy.
Lỗi hay gặp
catch rỗng. Lỗi bị nuốt mất, chương trình chạy sai mà không ai biết.
// SAI — lỗi xảy ra nhưng không ai hay
try {
int quantity = Integer.parseInt("abc");
} catch (Exception e) {
}// ĐÚNG — ít nhất phải báo cho người dùng
try {
int quantity = Integer.parseInt("abc");
} catch (NumberFormatException e) {
System.out.println("Số lượng không hợp lệ");
}Bắt Exception trước loại cụ thể. Exception bắt được mọi lỗi, nên
catch đứng sau nó không bao giờ chạy tới.
// SAI — lỗi compile: catch thứ hai không bao giờ chạy
try {
Integer.parseInt("abc");
} catch (Exception e) {
System.out.println("Có lỗi");
} catch (NumberFormatException e) {
System.out.println("Sai định dạng");
}// ĐÚNG — loại cụ thể đứng trước
try {
Integer.parseInt("abc");
} catch (NumberFormatException e) {
System.out.println("Sai định dạng");
} catch (Exception e) {
System.out.println("Có lỗi");
}Tóm tắt
- Exception là lỗi lúc chạy, không bắt thì chương trình dừng.
trychứa code có thể lỗi,catchxử lý lỗi,finallyluôn chạy.- Bắt đúng loại exception cụ thể và đặt nó trước
Exception. Không đểcatchrỗng. - Dùng
throwkhi dữ liệu không hợp lệ, đừng âm thầm chạy tiếp. - Checked exception như
IOExceptionphải đượccatchhoặc ghithrows, nếu không sẽ lỗi compile.
Tự kiểm tra
0/3 câuTrong try, Integer.parseInt("abc") ném NumberFormatException. Sau try chỉ có catch (IllegalStateException e). Chuyện gì xảy ra?
Method setPrice(long price) nhận giá âm. Cách xử lý nào hợp lý nhất?
Khối nào luôn chạy, dù try có lỗi hay không?