Java - Exception

1. Một số thuật ngữ:
- Exception: Một sự kiện "ngoại lệ" - ngoài mong muốn và làm cho luồng thực thi bị ngắt quãng, thay đổi, chấm dứt.
- Exception object: Khi exception xảy ra, runtime system sẽ sinh ra 1 đối tượng tương ứng với lỗi đấy (trong java người ta xây dựng sẵn các lớp của Exception - là các lớp con của java.lang.Throwable - các đối tượng này là các instance của các lớp). Các đối tượng này (object) chứa thông tin của các exception.
- Throwing an exception: Hành động tạo object và xử lý (gửi đi) trong runtime system.
- Call stack: Khi exception được throw, runtime system sẽ tìm kiếm các cách thức xử lý exception. Thứ tự tìm kiếm là các method theo thứ tự ngược với thứ tự gọi phương thức (nghĩa là tìm từ trên xuống):


Hình ảnh này gọi là Call stack
- Exception handler: Đoạn code mà sẽ xử lý exception.
- Catching an exception: Mỗi exception handler xử lý 1 loại exception khác nhau, một khi runtime system tìm thấy 1 handler phù hợp để xử lý, hành động đó gọi là catch
Nếu không tìm ra handler tương ứng, chương trình sẽ dừng lại.

2. Các loại exception:
Cos 3 loại:
a. Checked exception: Là exception mà có thể dự đoán được và khôi phục được, ví dụ các lỗi kiểm tra file có tồn tại không?...
b. Error: Lỗi bên ngoài chương trình, hay liên quan đến JVM, không dự đoán hay phục hồi được. Ví dụ: không đọc được file do phần cứng, hệ điều hành có vấn đề, JVM không tìm thấy platform class...
c. Runtime exception: Lỗi bên trong chương trình nhưng không dự đoán hay phục hồi được. Như các lỗi logic, gọi sai API...

3. Catch or Specify Requirement
Là 1 thủ tục yêu cầu chỉ định kiểm tra exception và tạo exception handler.
Đây là 1 thủ tục bắt buộc trong Java, với các checked exception, lập trình viên bắt buộc phải thực hiện thì mới biên dịch được.
Chỉ có loại Checked exception là bắt buộc phải thực hiện thủ tục này, 2 loại còn lại (unchecked) không cần.

Cách thức thực hiện:
Phần code xảy ra exception có thể ngầm định hoặc chỉ định rõ với câu lệnh:
throw new SomeException()
Và phần code này buộc phải:
   1. Hoặc nằm trong khối try ... catch
   2. Hoặc nằm trong method có mệnh đề throws SomeException đi kèm.

4. Khối try ... catch
Hãy xem xét ví dụ sau:

public static void readFile(String args[])
{
        Scanner sc = null;
        try {
            sc = new Scanner(new BufferedReader(new FileReader("abc.txt")));
            if (sc == null)
                throw new IOException ("File not found");
                   
            while (sc.hasNext()) {
                log(sc.next());
            }
        } catch (IOException e) {
            log("Error: " + e.getMessage());
        }
}


Đoạn code:
     if (sc == null)
                throw new IOException ("File not found");
không có cũng được (có thể ngầm định).


Trong khối try là các lệnh có thể xảy ra exception và khi xảy ra, runtime system sẽ tìm handler theo thứ tự:
- FileReader -> không có
- method readFile -> có 1 handler phù hợp (IOException) -> thực thi lệnh trong catch.

Chúng ta đôi khi thấy 1 dạng khối có thêm finally như vầy:

public static void readFile(String args[])
{
        Scanner sc = null;
        try {
            sc = new Scanner(new BufferedReader(new FileReader("abc.txt")));
            if (sc == null)
                throw new IOException ("File not found");
                   
            while (sc.hasNext()) {
                log(sc.next());
            }
        } catch (IOException e) {
            log("Error: " + e.getMessage());
        } finally {
            if (sc != null)
                sc.close();
        }
}

Trong khối finally thường là lệnh dọn dẹp, nó được thực hiện ngay khi khối lệnh try thoát ra và catch phù hợp nếu được tìm thấy (try --> catch phù hợp --> finaaly)

5. Throws statement:

Hãy xem ví dụ sau:

public static void readFile(String args[]) throws IOException
{
            Scanner sc = null;
            sc = new Scanner(new BufferedReader(new FileReader("abc.txt")));
            if (sc == null)              // không bắt buộc
                throw new IOException ("File not found");    // không bắt buộc
                  
            while (sc.hasNext()) {
                log(sc.next());
            }
}

Đây là cách 2 mà chúng ta nói tới. Khi đó, hàm gọi tói phương thức readFile (ví dụ là main) phải như thế này:

public static void main(String args[])
{
       try {
            readFile(args);
        }
        catch (IOException e) {
            log("Error: " + e.getMessage());
        }
}

(Nói chung là trước sau gì cũng phải catch Exception)

Dạng thức chung của nó là:
try {
...
// throw statement (có thể là phương thức, có thể là throw new...) hoặc không có throw...
} catch (...) {
...
}

6. Class tự tạo để xử lý Exception
Đôi khi ta hay gặp câu lệnh:
throw new MyException(); // MyException là user-define class

Cũng khá đơn giản, bạn chỉ việc tạo thêm class MyException:

class MyException extends NegativeArraySizeException
{
    MyException() {
        super("MyException occur !");
    }
}
public static void test(String args[]) throws MyException
    {
        int i = -1;
        if (i < 0)
            throw new MyException();
    }
public static void main(String args[])
    {
        try {
            test(args);
        }
        catch (MyException e) {
            log("Error: " + e);
        }
    }

Nhận xét