Khối Lệnh try (The Try Block)
Bước đầu tiên để xây dựng một trình xử lý ngoại lệ là bao bọc đoạn mã có khả năng gây ra ngoại lệ trong một khối try. Khối try phải được đặt bên trong một phương thức.
Nếu một ngoại lệ xảy ra tại một câu lệnh cụ thể trong khối try, phần còn lại của mã trong khối đó sẽ không được thực thi. Vì vậy, không nên đặt mã không thể gây ngoại lệ vào trong khối try.
Khối try luôn phải được theo sau bởi ít nhất một khối catch hoặc một khối finally.
Ⅰ. Cú pháp của khối lệnh try
Trong Java, khối try có thể kết hợp với các khối catch và finally theo nhiều cách khác nhau. Dưới đây là các tổ hợp hợp lệ của khối try, catch, và finally:
1. Khối try với catch
Khối try có thể đi kèm với ít nhất một khối catch.
Đây là cách kết hợp phổ biến nhất và thường được sử dụng để bắt và xử lý ngoại lệ.
Khi một ngoại lệ xảy ra trong khối try, chương trình sẽ chuyển ngay đến khối catch tương ứng để xử lý.
Nếu không có ngoại lệ nào xảy ra, khối catch sẽ bị bỏ qua.
Cú pháp
try {
// Mã có thể gây ra ngoại lệ
} catch (loại_ngoại_lệ biến_ngoại_lệ) {
// Xử lý ngoại lệ
}
Giải thích:
↳ try: Khối mã mà bạn muốn kiểm tra xem có xảy ra ngoại lệ không.
↳ catch: Khối mã được thực hiện nếu ngoại lệ xảy ra. loại_ngoại_lệ là kiểu ngoại lệ mà bạn muốn bắt.
2. Khối try với finally
Khối try có thể đi kèm với một khối finally mà không cần có khối catch.
Khối finally luôn được thực thi, dù có ngoại lệ xảy ra hay không.
Thường được sử dụng để giải phóng tài nguyên (như đóng file, kết nối cơ sở dữ liệu) hoặc thực hiện các tác vụ dọn dẹp khác.
Cú pháp
try {
// Các câu lệnh có thể gây ra ngoại lệ
} finally {
// Các câu lệnh dọn dẹp hoặc mã luôn được thực hiện
}
Giải thích:
↳ try: Khối mã mà bạn muốn kiểm tra xem có xảy ra ngoại lệ không.
↳ finally: Khối mã luôn được thực hiện, dù có ngoại lệ xảy ra hay không.
3. Khối try với catch và finally
Khối try có thể đi kèm với cả khối catch và finally.
Đây là cách kết hợp hoàn chỉnh nhất, cho phép bạn cả bắt ngoại lệ và đảm bảo các tài nguyên được giải phóng.
Nếu có ngoại lệ xảy ra, khối catch sẽ được thực thi trước, sau đó đến khối finally.
Nếu không có ngoại lệ, chỉ có khối finally được thực thi.
Cú pháp
try {
// Mã có thể gây ra ngoại lệ
} catch (loại_ngoại_lệ biến_ngoại_lệ) {
// Xử lý ngoại lệ
} finally {
// Mã luôn được thực hiện, có hoặc không có ngoại lệ
}
Giải thích:
↳ try: Khối mã mà bạn muốn kiểm tra xem có xảy ra ngoại lệ không.
↳ catch: Khối mã được thực hiện nếu ngoại lệ xảy ra. loại_ngoại_lệ là kiểu ngoại lệ mà bạn muốn bắt.
↳ finally: Khối mã luôn được thực hiện, dù có ngoại lệ xảy ra hay không.
4. Khối try với nhiều catch và finally
Bạn có thể sử dụng khối try đi kèm với nhiều khối catch để xử lý các loại ngoại lệ khác nhau, và có thể có một khối finally.
Thứ tự của các khối catch rất quan trọng. Khối catch được đặt trước sẽ được ưu tiên thực thi nếu loại ngoại lệ của nó phù hợp.
Khối finally luôn được thực thi cuối cùng.
Cú pháp
try {
// Mã có thể gây ra ngoại lệ
} catch (loại_ngoại_lệ1 biến_ngoại_lệ1) {
// Xử lý ngoại lệ 1
}catch (loại_ngoại_lệ2 biến_ngoại_lệ2) {
// Xử lý ngoại lệ 2
}finally {
// Mã luôn được thực hiện, có hoặc không có ngoại lệ
}
Ⅱ. Hoạt động bên trong của khối try-catch
Khi chương trình Java thực thi đến một khối try, nó sẽ bắt đầu thực hiện các câu lệnh bên trong. Nếu không có ngoại lệ nào xảy ra, các câu lệnh trong khối try sẽ được thực thi đến hết và chương trình sẽ tiếp tục với câu lệnh tiếp theo sau khối finally (nếu có).
Tuy nhiên, nếu một ngoại lệ xảy ra bên trong khối try:
↳ Ngắt thực thi: Ngay lập tức, quá trình thực thi của khối try sẽ bị dừng lại tại vị trí xảy ra ngoại lệ.
↳ Tìm kiếm khối catch phù hợp: Chương trình sẽ tìm kiếm các khối catch theo thứ tự chúng được khai báo.
↳ Thực thi khối catch: Nếu tìm thấy một khối catch có thể xử lý loại ngoại lệ đó (tức là kiểu ngoại lệ được khai báo trong catch là lớp cha hoặc là chính xác loại ngoại lệ đang xảy ra), khối catch đó sẽ được thực thi.
↳ Bỏ qua các khối catch còn lại: Các khối catch còn lại sẽ bị bỏ qua.
↳ Thực thi khối finally (nếu có): Sau khi khối catch được thực thi xong, chương trình sẽ chuyển đến khối finally (nếu có) để thực hiện các tác vụ dọn dẹp.
Lưu ý:
Thứ tự các khối catch: Việc sắp xếp các khối catch là quan trọng. Khối catch cho các loại ngoại lệ cụ thể hơn nên được đặt trước các khối catch cho các loại ngoại lệ chung hơn (như Exception).
Khối finally: Khối finally luôn được thực thi, dù có ngoại lệ xảy ra hay không. Đây là nơi lý tưởng để giải phóng tài nguyên, đóng kết nối, hoặc thực hiện các tác vụ dọn dẹp khác.
Không bắt ngoại lệ quá chung: Việc bắt ngoại lệ quá chung (như Exception) có thể che giấu các lỗi tiềm ẩn và làm khó khăn cho việc gỡ lỗi.

Vấn đề không có ngoại lệ xử lý
Trong ví dụ này, không có xử lý ngoại lệ. Khi ngoại lệ xảy ra, chương trình sẽ dừng và hiển thị thông báo lỗi.
Ví dụ: Example.java
public class Example {
public static void main(String[] args) {
System.out.println("Bắt đầu chương trình");
// Cố gắng chia cho 0
int result = 10 / 0;
// Những dòng này sẽ không được thực thi
System.out.println("Kết quả: " + result);
System.out.println("Kết thúc chương trình");
}
}
Kết quả của chương trình là:
Exception in thread "main" java.lang.ArithmeticException: / by zero at Example.main(Example.java:6)
Khi chạy chương trình này, bạn sẽ nhận được thông báo lỗi và chương trình sẽ dừng.
Giải quyết bằng xử lý ngoại lệ
Trong ví dụ này, ngoại lệ được xử lý bằng khối try-catch, do đó chương trình có thể tiếp tục thực thi sau khi ngoại lệ xảy ra.
Ví dụ: Example.java
public class Example {
public static void main(String[] args) {
System.out.println("Bắt đầu chương trình");
try {
// Cố gắng chia cho 0
int result = 10 / 0;
System.out.println("Kết quả: " + result);
} catch (ArithmeticException e) {
// Bắt ngoại lệ và xử lý
System.out.println("Ngoại lệ xảy ra: " + e.getMessage());
}
// Những dòng này sẽ được thực thi
System.out.println("Kết thúc chương trình");
}
}
Kết quả của chương trình là:
Ngoại lệ xảy ra: / by zero
Kết thúc chương trình
Khi chạy chương trình này, bạn sẽ thấy rằng chương trình tiếp tục chạy sau khi ngoại lệ xảy ra.
Giải Thích:
↳ Không xử lý ngoại lệ: Khi một ngoại lệ xảy ra (ví dụ: chia cho 0), chương trình dừng ngay lập tức và hiển thị thông báo lỗi. Các dòng mã sau ngoại lệ không được thực thi.
↳ Có xử lý ngoại lệ: Khi ngoại lệ xảy ra, khối catch bắt và xử lý ngoại lệ, do đó chương trình có thể tiếp tục thực thi các dòng mã sau khối try-catch. Điều này giúp chương trình duy trì luồng thực thi bình thường và tránh việc dừng đột ngột.
↳ Việc xử lý ngoại lệ trong Java giúp bạn viết mã an toàn và ổn định hơn, đảm bảo rằng chương trình của bạn có thể xử lý các tình huống lỗi một cách thông minh và không bị dừng đột ngột khi gặp lỗi.