25/05/2018, 07:26

Ngoại lệ (EXCEPTION) trong Java

Trong chương trình, có một số các "thao tác không chắc chắn", ví dụ như các thao tác vào/ra: đĩa mềm chưa sẵn sàng, máy in có lỗi, nối kết mạng không thực hiện được, . . . sẽ dẫn đến lỗi thực thi chương trình. Java hạn chế các lỗi ...

Trong chương trình, có một số các "thao tác không chắc chắn",  ví dụ như các thao tác vào/ra: đĩa mềm chưa sẵn sàng, máy in có lỗi, nối kết mạng không thực hiện được, . . . sẽ dẫn đến lỗi thực thi chương trình.

Java hạn chế các lỗi sinh ra từ "thao tác không chắc chắn" bằng cơ chế Ngoại lệ (Exception). 

Ngoại lệ tức là một sự kiện xảy ra ngoài dự tính của chương trình nếu không xử lý sẽ làm cho chương trình chuyển sang trạng thái không còn kiểm soát được. Ví dụ điều gì sẽ xảy ra nếu chương trình truy xuất đến phần tử thứ 11 của một mảng 10 phần tử ? Một số ngôn ngữ như C, C++ sẽ không báo lỗi gì cả, chương trình vẫn tiếp tục vận hành nhưng kết quả thì không thể xác định được.

Để hạn chế những lỗi như thế, Java bắt buộc các lệnh có thể dẫn đến các ngoại lệ phải có các đoạn mã xử lý phòng hờ khi ngoại lệ xảy ra theo cú pháp sau:

try { Các thao tác vào ra có thể sinh ra các ngoại lệ. }catch (KiểuNgoạiLệ_01 biến) { ứng xử khi ngoại lệ KiểuNgoaiLệ_01 sinh ra } catch (KiểuNgoạiLệ_02 biến) { ứng xử khi ngoại lệ KiểuNgoaiLệ_02 sinh ra }finally { Công việc luôn luôn được thực hiện }

Trong cơ chế này, các lệnh có thể tạo ra ngoại lệ  sẽ được đưa vào trong khối bao bọc bởi từ khóa try {}. Tiếp theo đó là một loạt các khối catch{}. Một lệnh có thể sinh ra một hoặc nhiều loại ngoại lệ. Ứng với một loại ngoại lệ sẽ có một khối catch{} để xử lý cho loại ngoại lệ đó. Tham số của catch chỉ ra loại ngoại lệ mà nó có trách nhiệm xử lý. Khi thực thi chương trình, nếu một lệnh nào đó nằm trong khối try{} tạo ra ngoại lệ, điều khiển sẽ được  chuyển sang các lệnh nằm trong các khối catch{} tương ứng với loại ngoại lệ đó. Các lệnh phía sau lệnh tạo ra ngoại lệ trong khối try{} sẽ bị bỏ qua. Các lệnh nằm trong khối finally{} thì luôn luôn được thực hiện cho dù có xảy ra ngoại lệ hay là không. Khối lệnh finally{} là tùy chọn có thể không cần.

Ngoại lệ có loại bắt buộc phải  xử lý,  tức phải có try{}, có catch{} khi sử dụng lệnh đó. Ví dụ như lệnh đọc từ bàn phím. Trình biên dịch của java sẽ báo lỗi  nếu chúng ta không xử lý chúng.

Ngược lại, có loại ngoại lệ không bắt buộc phải xử lý, ví dụ như truy xuất đến phần tử bên ngoài chỉ số mảng. 

Tra cứu tài liệu đặc tả các API của java để biết được các ngoại lệ tạo ra từ một phương thức.

Ví dụ:  

Lưu chương trình sau vào tập tin ExceptionDemo.java :

public class ExceptionDemo {    public static void main(String[] args) {        try {            System.out.println("Hello " + args[0]);        }        catch (ArrayIndexOutOfBoundsException e){            System.out.println("Hello Whoever you are.");        }        finally {            System.out.println("How are you?");         }    }}

Biên dịch và thực thi có kết quả như sau:

Kết quả biên dịch chương trình ExceptionDemo.java

Trong chương trình trên chúng ta dự định sẽ chào người được đưa vào từ đối số thứ nhất của chương tình (được chứa trong phần tử args[0]). Tuy nhiên nếu người dùng thực thi chương trình quên đưa vào đối số, tức phần tử args[0] không tồn tại. Ngoại lệ báo hiệu truy xuất đến phần tử nằm ngoài mảng (ArrayIndexOutOfBoundsException) được quẳng ra (throw). Khi đó đoạn mã lệnh trong khối catch có tham số là loại ngoại lệ ArrayIndexOutOfBoundsException sẽ đưọc thực hiện.   

0