Checked và Unchecked Exception trong java

Exception là một sự kiện bất ngờ xảy ra trong quá trình thực thi chương trình làm phá vỡ luồng chạy bình thường của chương trình. Chúng ta có hai loại exception là:

  • Checked
  • Unchecked

CheckedException

CheckedException là những exception có thể nhìn thấy và kiểm tra tại thời điểm biên dịch. Nếu trong code có bất kỳ method nào ném CheckedException thì chúng ta phải xử lý chúng hoặc sử dụng từ khoá throws đẩy lên cho method tầng trên xử lý(các method khác sử dụng chúng).

import java.io.*; 
  
class Main { 
    public static void main(String[] args) {
        BufferedReader fileInput = null;
        FileReader file = new FileReader("C:\\test\\a.txt"); 
        fileInput = new BufferedReader(file); 
          
        // Print first 3 lines of file "C:\test\a.txt" 
        for (int counter = 0; counter < 3; counter++)  
            System.out.println(fileInput.readLine()); 
          
        fileInput.close(); 
    } 
}

Output

Exception in thread “main” java.lang.RuntimeException: Uncompilable source code – unreported exception java.io.FileNotFoundException; must be caught or declared to be thrown at Main.main(Main.java:5)

Ở đoạn code ở trên chương trình sẽ tiến hành mở file và in ra màn hình 3 dòng đầu tiên của file a.txt. Thế nhưng khi compile sẽ bị lỗi vì constructor FileReader() ném checked exception FileNotFoundException, readLine()close() cũng ném IOException. 

Để sửa đoạn code trên chúng ta 2 cách:

Sử dụng try-catch để xử lý checkedException

Sử dụng try-catch bao bên ngoài khối lệnh có thể ném ra exception. Khi có một exception xảy ra trong khối lệnh try chúng sẽ được xử lý trong khối lệnh catch. Ở đây mình chỉ xử lý đơn giản là in ra màn lỗi.

import java.io.*;

class Main {
    public static void main(String[] args) {
        BufferedReader fileInput = null;
        try {
            FileReader file = new FileReader("C:\\test\\a.txt");
            fileInput = new BufferedReader(file);
            // Print first 3 lines of file "C:\test\a.txt"
            for (int counter = 0; counter < 3; counter++)
                System.out.println(fileInput.readLine());

            fileInput.close();
        } catch (FileNotFoundException e) {
            System.out.println("FileNotFoundException roi!!!");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("IOException roi!!!");
            e.printStackTrace();
        }
    }
}

Vì trong khối lệnh try có thể ném ra đến 2 exception là IOException và FileNotFoundException nên chúng ta phải xử lý cho từng Exception một. Lưu ý thứ tự catch Exception trên là bắt buộc vì FileNotFoundException là một subclass của IOException, khối lệnh catch sẽ kiểm tra từ trên xuống khi chúng thấy một exception nào hợp lệ thì các khối catch bên dưới sẽ không được thực thi. Vì FileNotFoundException là subclass của IOException nên để phía sau thì nó sẽ khiến cho FileNotFoundException không bao giờ được thực hiện.

Sử dụng từ khoá throws để xử lý CheckedException

Sử dụng từ khoá throws liệt kê tất cả các exception có thể xảy ra bên trong method. Các method khác khi sử dụng method này phải xử lý các exception được chỉ định với từ khoá throws. Cách xử lý cũng tương tự có 2 cách là try-catchthrows. Nếu đến cuối cùng vẫn không có method này xử lý các exception được ném ra thì chương trình sẽ báo lỗi đến người dùng và có thể gây crash chương trình, đây là điều tối kỵ đối với một ứng dụng.

import java.io.*;

class Main {
    public static void main(String[] args) throws IOException{
        BufferedReader fileInput = null;
            FileReader file = new FileReader("C:\\test\\a.txt");
            fileInput = new BufferedReader(file);
            // Print first 3 lines of file "C:\test\a.txt"
            for (int counter = 0; counter < 3; counter++)
                System.out.println(fileInput.readLine());

            fileInput.close();
        }
    }
}

Chúng ta chỉ cần throws IOException vì nó đã bao gồm FileNotFoundException.

UncheckedException

UncheckedException là các exception không được kiểm tra tại thời điểm biên dịch. Hầu hết các unchecked exception xảy ra do dữ liệu không hợp lệ trong quá trình tương tác với chương trình. Bắt buộc chúng ta phải thêm các điều kiện để kiểm tra dữ liệu nhầm đảm bảo chương trình chạy đúng cho mọi trường hợp. 

class Example {  
   public static void main(String args[])
   {
	int num1=10;
	int num2=0;
	/*Since I'm dividing an integer with 0
	 * it should throw ArithmeticException
         */
	int res=num1/num2;
	System.out.println(res);
   }
}

Đoạn code trên khi chúng ta compile sẽ không gây bất kỳ lỗi nào nhưng nếu chạy thì chúng ta sẽ bị ném ArithmeticException.

Hoặc 

class Example {  
   public static void main(String args[])
   {
	int arr[] ={1,2,3,4,5};
	/* My array has only 5 elements but we are trying to 
         * display the value of 8th element. It should throw
	 * ArrayIndexOutOfBoundsException
         */
	System.out.println(arr[7]);
   }
}

Sẽ gây ra lỗi ArrayIndexOutOfBoundsException vì chỉ số phần tử lớn nhất trong arr là 4.

Chúng ta hoàn toàn có thể sử dụng try-catch hoặc throws exception như thế này!

class Example {
    public static void main(String args[]) {
        try {
            int arr[] = {1, 2, 3, 4, 5};
            /* My array has only 5 elements but we are trying to
             * display the value of 8th element. It should throw
             * ArrayIndexOutOfBoundsException
             */
            System.out.println(arr[7]);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Sai roi");
        }

    }
}

Thế nhưng đừng làm vậy nhé, vì các lỗi này chúng ta có thể tránh bằng việc thêm các điều kiện kiểm tra. Người ta có câu “Phòng bệnh hơn chữa bệnh” mà. 

class Example {
    public static void main(String args[]) {
        int arr[] = {1, 2, 3, 4, 5};

        int index = 7;
        if (arr.length >= 8) {
            System.out.println(arr[index]);
        } else
            System.out.println("Sai roi");
    }

}

Trường hợp sử dụng checked và unchecked exception

Có thể thấy checked và unchecked exception có ý nghĩa hoàn toàn khác nhau, do đó chúng ta cần xác định rõ trong trường nào thì sử dụng checked exception và trong trường hợp nào thì dùng unchecked exception.

Theo tài liệu từ Oracle, họ phát biểu như sau:

If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception.

Tạm dịch: Nếu một exception xảy ra mà người dùng có thể khắc phục được thì sử dụng checked exception, còn nếu một exception khi xảy ra mà người dùng không thể làm gì để khắc phục thì sử dụng unchecked exception.

Ví dụ, khi người dùng mở một file, chúng ta có thể kiểm tra tên file nhập vào có hợp lệ hay không, nếu không thì chúng ta có thể yêu cầu người dùng nhập tên file khác hợp lệ. Trong trường hợp này chúng ta sẽ sử dụng checked exception.

Tuy nhiên, trường hợp tên file đã hợp lệ nhưng nhưng ai đó đã xóa file này trước đó hoặc hệ thông có lỗi gì đó không mở được file thì trong trường hợp này chúng ta sử dụng unchecked exception.

Tóm lược

Qua đây thì chúng ta đã có cái nhìn tổng quan về Exception trong java và cách xử lý trong từng tình huống cụ thể. Các bạn cần phân biệt CheckedException là các exception mà chúng ta cần có phương án xử lý cụ thể khi nó xảy ra còn đối với Unchecked thì chúng ta hoàn hoàn có thể phòng ngừa bằng việc thêm các điều kiện kiểm tra dữ liệu đầu vào trước khi thực hiện các thao tác khác. 

Nguồn tham khảo

https://beginnersbook.com/2013/04/java-checked-unchecked-exceptions-with-examples/

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x