Các ngoại lệ (exceptions)

Một ngoại lệ (exception) là một vấn đề xuất hiện trong quá trình thực thi chương trình. Khi một ngoại lệ xuất hiện, chương trình sẽ bị ngắt và dừng đột ngột mà không có bất kỳ gợi ý nào, vì vậy, các ngoại lệ này cần phải được xử lý.

Ngoại lệ xuất hiện bởi nhiều lý do như người dùng nhập dữ liệu không hợp lệ, tập tin không được tìm thấy hay kết nối mạng bị ngắt, v.v.

Một vài ngoại lệ do người dùng, một vài do lỗi người lập trình, và một vài do sự hạn chế của các tài nguyên vật lý. Căn cứ vào những điều này, ngoại lệ có thể chia thành 3 loại:

– Ngoại lệ xuất hiện trong thời gian biên dịch (the compile time) được gọi là các ngoại lệ được kiểm tra (checked exceptions). Ví dụ cho kiểu ngoại lệ này là ngoại lệ FileNotFoundException được phát sinh nếu một tập tin không tồn tại khi sử dụng đối tượng FileReader như ví dụ sau:


File file = new File("E://file.txt");

FileReader fr = new FileReader(file);

Ngoại lệ có thể trông như sau:

– Ngoại lệ xuất hiện trong thời gian thực thi (the time of execution) được gọi là các ngoại lệ không được kiểm tra (unchecked exceptions). Các ngoại lệ này thường do các lỗi khi lập trình như lỗi logic (liên quan đến thuật toán) hay lỗi cú pháp. Ví dụ cho kiểu ngoại lệ này là ArrayIndexOutOfBoundsExceptionexception xuất hiện khi chúng ta truy cập đến phạm vi vượt quá giới hạn của một mảng như ví dụ sau:


int num[] = {1, 2, 3, 4};

System.out.println(num[5]);

Ngoại lệ có thể trông như sau:

– Ngoại lệ phát sinh do các lỗi vượt qua sự kiểm soát của người dùng hay người lập trình. Một ví dụ là lỗi tràn bộ nhớ.

Cấu trúc ngoại lệ trong Java (Exception hierarchy)

Các ngoại lệ và các lỗi trong Java được tổ chức theo cấu trúc sau:

Như sơ đồ trên, tất cả các lớp ngoại lệ đều là các lớp con của lớp Exceptions. Các lỗi được tập hợp trong lớp Errors. Cả hai lớp ExceptionsErrors đều là con của lớp Throwable.

Xử lý ngoại lệ (handling exceptions)

Sử dụng khối lệnh try/catch/finally

Cách xử lý ngoại lệ phổ biến nhất và hiệu quả nhất là sử dụng khối lệnh try/catch:


try {

// Khối lệnh thực thi

} catch (ExceptionName e1) {

// Khối lệnh thực thi khi ngoại lệ xuất hiện

}

ExceptionName là tên của ngoại lệ mà chúng ta muốn xử lý khi nó xuất hiện ví dụ FileNotFoundException hay ArrayIndexOutOfBoundsExceptionexception. Sau try là khối lệnh thực thi cần được bảo vệ từ các ngoại lệ; khối lệnh trong catch sẽ thực thi nếu ngoại lệ ExceptionName xuất hiện.

Cũng có thể có nhiều lệnh catch sau try:


try {

// Khối lệnh thực thi

} catch (ExceptionType1 e1) {

// Khối lệnh thực thi khi ngoại lệ ExceptionType1 xuất hiện

} catch (ExceptionType2 e2) {

// Khối lệnh thực thi khi ngoại lệ ExceptionType2 xuất hiện

} catch (ExceptionType3 e3) {

// Khối lệnh thực thi khi ngoại lệ ExceptionType3 xuất hiện

}

Lệnh finally cũng có thể được sử dụng theo sau try hay catch nhưng thông thường là theo thứ tự try/catch/finally:


try {

// Khối lệnh thực thi

} catch (ExceptionName e1) {

// Khối lệnh thực thi khi ngoại lệ xuất hiện

} finally {

// Khối lệnh luôn luôn thực thi

}

Khối lệnh finally luôn luôn thực thi bất kế ngoại lệ có xuất hiện hay không.

Đoạn chương trình sau minh họa cách sử dụng try/catch/finally:


public static void main(String[] args) {

// TODO Auto-generated method stub

int so_bi_chia;// số bị chia

int so_chia;// số chia

Scanner scanner = new Scanner(System.in);

System.out.println("Nhap so bi chia: ");

so_bi_chia = Integer.parseInt(scanner.nextLine());

System.out.println("Nhap so chia: ");

so_chia = Integer.parseInt(scanner.nextLine());

try {

System.out.println(so_bi_chia + " / " + so_chia +

" = " + (so_bi_chia / so_chia) + " So du là: " +

(so_bi_chia % so_chia));

}catch(ArithmeticException e) {

System.out.println("Khong the chia cho 0!");

}finally {

System.out.println("Ket thuc chuong trinh.");

}

}

Thực thi chương trình:


Nhap so bi chia: 3

Nhap so chia: 0

Khong the chia cho 0!

Ket thuc chuong trinh.

Sử dụng throw và throws

Nếu một phương thức không xử lý kiểu ngoại lệ được kiểm tra (checked exception) như FileNotFoundException thì phương thức phải được khai báo với từ khóa throws, ví dụ phương thức main sử dụng đối tượng FileReader:


public static void main(String[] args)  {

// TODO Auto-generated method stub

File file = new File("E://file.txt");

FileReader fr = new FileReader(file);

}

Phương thức main trên sẽ có lỗi trong như sau:

Chỉ cần thêm khai báo throws:


public static void main(String[] args) throws FileNotFoundException  {

// TODO Auto-generated method stub

File file = new File("E://file.txt");

FileReader fr = new FileReader(file);

}

Khai báo với throws không dùng để xử lý ngoại lệ mà chỉ dùng để trì hoãn xử lý ngoại lệ. Nếu thực thi phương thức main trên vẫn sẽ phát sinh ngoại lệ.

Khác với throws, lệnh throw dùng để phát sinh một ngoại lệ cụ thể, ví dụ:


throw new FileNotFoundException();

Ngôn ngữ Java >