I. Exception là gì?

1.  Giới thiệu:

Exception  là 1 lỗi đặc biệt, lỗi này xuất hiện vào lúc thực thi chương trình. Các trạng thái không bình thường xảy ra trong khi thực thi chương trình tạo ra các Exception(Những trạng thái này không được biết trước trong khi ta xây dựng chương trình). Ví dụ: Với phép toán chia, người dùng nhập số từ bàn phím vào, việc chia cho 0 sẽ tạo một lỗi trong chương trình.

2. Mục đích của việc xử lí ngoại lệ.

Một chương trình nên có cơ chế xử lý ngoại lệ thích hợp. Nếu không, chương trình sẽ bị ngắt khi một exception xảy ra. Trong trường hợp đó, tất cả các nguồn tài nguyên mà hệ thống trước kia phân phối sẽ được di dời trong cùng trạng thái. Điều này gây lãng phí tài nguyên. Để tránh trường hợp này, tất cả các nguồn tài nguyên mà hệ thống phân phối nên được thu hồi lại. 

Khi một ngoại lệ xảy ra, đối tượng tương ứng với ngoại lệ đó được tạo ra. Đối tượng này sau đó được truyền cho phương thức là nơi mà ngoại lệ xảy ra. Đối tượng này chứa thông tin chi tiết về ngoại lệ. Thông tin này có thể được nhận về và được xử lý.

II. Mô hình xử lí ngoại lệ.

Trong Java, mô hình xử lý ngoại lệ kiểm tra việc xử lý những lỗi, được biết đến là mô hình ‘catch và throw’. Trong mô hình này, khi một lỗi xảy ra, một ngoại lệ sẽ bị chặn và được đưa vào trong một khối. Người lập trình viên nên xét các trạng thái ngoại lệ độc lập nhau từ việc điều khiển thông thường trong chương trình. Các ngoại lệ phải được catch nếu không chương  trình sẽ bị ngắt.

Ngôn ngữ java cung câp 5 từ khóa sau để xử lý các ngoại lệ:

  • try
  • catch
  • throw
  • throws
  • finally
  • Syntax:
try {

}
catch(Exception e1) {

// If an exception is thrown in ‘try’, which is of type e1, then perform 

// necessary actions here, else go to the next catch block 

}
catch(Exception e2){
// If an exception is thrown in, try which is of type e2, then perform
// necessary actions here, else go to the next catch block
}
catch(Exception eN){
// If an exception is thrown in, try which is of type eN, then perform
// necessary actions here, else go to the next catch block
}
finally{
// this book is executed, whether or not the exception is throw.
}

2.1. Tại sao cần try- catch?

Khối ‘try-catch’ được sử dụng để thi hành mô hình ‘catch và throw’ của việc xử lý ngoại lệ.
Khối ‘try’ chứa một bộ các lệnh có thể thi hành được. Các ngoại lệ có thể bị chặn khi thi hành những câu lệnh này. Phương thức dùng để chặn ngoại lệ có thể được khai báo trong khối ‘try’.  Một hay nhiều khối ‘catch’ có thể theo sau khối ‘try’. Các khối ‘catch’ này bắt các ngoại lệ bị chặn trong khối ‘try’. Hãy nhìn khối ‘try’ dưới đây:

try{
doFileProcessing();
// user-defined method
displayResults();
}
catch (Exception e){
// exception object
System.err.println(“Error :” + e.toString());
e.printStackTrace();
}


Ở đây, ‘e’ là đối tượng của lớp ‘Exception’. Chúng ta có thể sử dụng đối tượng này để in các chi tiết về ngoại lệ. Các phương thức ‘toString’ và ‘printStackTrace’ được sử dụng để mô tả các exception phát sinh ra. Hình sau chỉ ra kết xuất của phương thức ‘printStackTrace()’.

Để bắt giữ bất cứ ngoại lệ nào, ta phải chỉ ra kiểu ngoại lệ là ‘Exception’.

Catch(Exception e)

Khi ngoại lệ bị bắt giữ không biết thuộc kiểu nào, chúng ta có thể sử dụng lớp ‘Exception’ để bắt ngoại lệ đó. Khối ‘catch()’ bắt giữ bất cứ các lỗi xảy ra trong khi thi hành phương thức ‘doFileProcessing’ hay ‘display’. Nếu một lỗi xảy ra trong khi thi hành phương thức ‘doFileProcessing()’, lúc đó phương thức ‘displayResults()’ sẽ không bao giờ được gọi. Sự thi hành sẽ tiếp tục thực hiện khối ‘catch’. Để có nhiều lớp xử lý lỗi hơn, như là ‘LookupException’ thay vì một đối tượng ngoại lệ chung (Exception e), lỗi thật sự sẽ là một instance của ‘LookupException’ hay một trong số những lớp con của nó. Lỗi sẽ được truyền qua khối ‘try catch’ cho tới khi chúng bắt gặp một ‘catch’ tham chiếu tới nó hay
toàn bộ chương trình phải bị huỷ bỏ.

2.2. Cú pháp try – catch.

– Để xử lí exception, các nhà phát triển cần phải xử lý các báo cáo, điều đố có thể dẫn đến trường hợp exception và kèm theo chúng trong một khối try. Trường hợp exception cần phải được liên kết với một khối try bằng cách cung cấp một hoặc nhiều khối catch trực tiếp sau khối try.

-Cú pháp try – catch:

try { . . . 

} catch (ExceptionType name) {

}

-Khối catch trong java được sử dụng để xử lý các exception,nó phải được sử dụng sau khối thử try.Bạn có thể sử dụng nhiều khối catch với một khối try đơn.Code trong khối catch được thực thi nếu xử lý exception gọi tới nó.

2.3 .Throws và throw là gì?

– Throws: 
Từ khóa throws trong java được sử dụng để khai báo 1 exception. Nó cung cấp  1 thông tin tới Lập trình viên rằng có thể xuất hiện 1 Exception, để họ nên cung cấp 1 code để xử lý ngoại lệ, để duy trì luồng chuẩn của chương trình. Xử lý ngoại lệ (Exception Handing) chủ yếu được sử dụng để xử lý các Checked Exception. Nếu có thể xuất hiện bất cứ Unchecked Exception nào, chẳng hạn như NullPointerException, thì đó là lỗi của lập trình viên vì họ đã không thực hiện kiểm tra code trước khi sử dụng.

-Cú pháp throws:

return_type method_name() throws exception_class_name{
// method name
}

Đoạn mã sau minh họa cách sử dụng của từ khoá ‘throws’ để xử lý nhiều ngoại lệ:
public class Example {
// multiple exceptions separated by a comma
    public void exceptionExample() throws ExException, LookupException {
       try {
           // statements
       } catch(ExException exmp) {

       } catch(LookupException lkpex)

       {
       }
    }
}
Trong ví dụ trên, phương thức ‘exceptionExample’ khai báo từ khóa ‘throws’. Từ khóa này được theo bởi danh sách các ngoại lệ mà phương thức này có thể chặn. Trong trường hợp này là ‘Exception’ và ‘LookupException’. Hàm xử lý ngoại lệ cho các phương thức này nên khai báo các khối ‘catch’ để có thể xử lý tất cả các ngoại lệ mà các phương thức chặn. Lớp ‘Exception’ thực thi giao diện ‘Throwable’ và cung cấp các tính năng hữu dụng để phân phối các ngoại leek. Ưu điểm của nó là tạo các lớp ngoại lệ được định nghĩa bởi người dùng. Để làm điểu này, một lớp con của lớp Exception được tạo ra. Ưu điểm của lớp con là một kiểu ngoại lệ mới có thể bị bắt giữ độc lập từ các loại Throwable khác.

– Throw: Từ khóa throw trong Java được sử dụng để ném tường minh một exception. Chúng ta có thể ném hoặc Checked Exception hoặc Unchecked Exception trong Java bởi từ khóa throw. Từ khóa throw được sử dụng chủ yếu để ném các Custom Exception (là các exception được định nghĩa bởi lập trình viên).

-Cú pháp throw: throw exception;

try{

if (flag<0){

throw new MyException(); // user-defined

}

}

Một phương thức đơn có thể chặn nhiều ngoại lệ. Để xử lý những ngoại lệ này, ta cần cung cấp một danh sách các ngoại lệ mà phương thức chặn trong phần định nghĩa của phương thức. Giả sử rằng phương thức ‘x()’ gọi phương thức ‘y()’. Phương thức ‘y()’ chặn một ngoại lệ không được xử lý. Trong trường hợp này, phương thức gọi ‘x()’ nên khai báo việc chặn cùng một ngoại lệ với phương thức được gọi ‘y()’. Ta nên khai báo khối ‘try catch’ trong phương thức x() để đảm bảo rằng ngoại lệ không được truyền cho các phương thức mà gọi phương thức này.


-Ví dụ về throws và throw trong java.
17036491_1742562346073717_875705824_o

2.4.  Khối Finally

Khối finally trong là một khối được sử dụng để thực thi các phần code quan trọng như đóng kết nối, đóng stream, … Khối finally luôn luôn được thực thi dù cho exception có được xử lý hay không. Khối finally phải được theo sau bởi khối try hoặc khối catch.

Ghi chú: nếu bạn không xử lý ngoại lệ trước khi kết thúc chương trình, JVM sẽ thực thi khối finally (nếu bạn không có).

class FinallyDemo {
     String name;
     int no1,no2;
     FinallyDemo(String args[]){
     try {</span>
         <span class="fontstyle0">name=new String(“Aptech Limited”);
         no1=Integer.parseInt(args[0]);
         no2=Integer.parseInt(args[1]);
         System.out.println(name);
         System.out.println(“Division Result is” + no1/no2);
      }catch(ArithmeticException i) {
         System.out.println(“Cannot Divide by zero”);
      }
      finally {
         name=null; // clean up code
         System.out.println(“Finally executed”);
      }
}
      public static void main(String args[]) {
         new FinallyDemo(args);
      }
}

Sự sử dụng khối finally trong Java

Ví dụ 1 : Ở đây exeption không xuất hiện.

17036491_1742562346073717_875705824_o

17006069_1490927990953139_1005022576_n.png

Ví dụ 2 : exception xuất hiện và không được xử lý.

2.png

17035185_1490928000953138_275091939_n.png

Ví dụ 3 : exception xảy ra và được xử lý.3.png

3_n.png

Qui tắc: Với một khối try thì có thể có 0 hoặc nhiều khối catch, nhưng chỉ có một khối finally.

Ghi chú: Khối finally sẽ không được thực thi :

– Khi Java Virtual Machine (JVM) thoát ra trong khi try hoặc catch đang được thực hiện.
– Nếu thực hiện thread try hoặc catch đang bị gián đoạn hoặc bị loại bỏ .

2.5. Nhiều khối catch trong java

Nếu bạn phải thực hiện các tác vụ khác nhau mà có thể xảy ra các exception khác nhau, bạn sử dụng nhiều khối catch trong Java. Bạn theo dõi ví dụ đơn giản sau:

4.png

4_n.png

Qui tắc 1: Tại một thời điểm, chỉ một exception được xuất hiện và tại một thời điểm, chỉ có một khối catch được thực thi.

Qui tắc 2: Tất cả khối catch phải được sắp xếp từ cụ thể nhất tới chung nhất, ví dụ: việc bắt ArithimeticExption phải ở trước việc bắt Exception.

screenshot-7

Và nếu ko theo quy tắc thì trương trình sẽ cho ra lỗi.

2.6. Danh sách các ngoại lệ.

Capture3.JPG

III. Tự định nghĩa ngoại lệ. (Lớp exception tự định nghĩa)

Tại sao cần phải có các lớp exception do người dùng định nghĩa? Vì các ngoại lệ do hệ thống xây dựng không đủ để kiểm soát tất cả các lỗi.

  • Kế thừa từ một lớp Exception hoặc lớp con của nó.
  • Có tất cả các method của lớp Throwable.

Tạo ra 1 ngoại lệ:

public class MyException extends Exception {
public MyException(String msg) {
super(msg);
}
public MyException(String msg, Throwable cause){
super(msg, cause);
}

Sử dụng ngoại lệ tự định nghĩa:

public class FileExample
{
 public void copyFile(String fName1,String fName2)
throws MyException
 {
 if (fName1.equals(fName2))
 throw new MyException("File trung ten");
// Copy file
 System.out.println("Copy completed");
 }
}

Bắt và xử lí ngoại lệ:

public class Test {
public static void main(String[] args) {
 FileExample obj = new FileExample();
 try {
 String a = args[0];
String b = args[1];
obj.copyFile(a,b);
 } catch (MyException e1) {
 System.out.println(e1.getMessage());
 }
 catch(Exception e2) {
 System.out.println(e2.toString());
}

IV. Tóm tắt.

  • Bất cứ khi nào một lỗi xuất hiện trong khi thi hành chương trình, nghĩa là một ngoại lệ đã xuất hiện.
  • Ngoại lệ phát sinh vào lúc thực thi chương trình theo trình tự mã.
  • Mỗi ngoại lệ phát sinh ra phải bị bắt giữ , nếu không ứng dụng sẽ bị ngắt.
  • Việc xử lý ngoại lệ cho phép bạn kết hợp tất cả tiến trình xử lý lỗi trong một nơi. Lúc
    đó đoạn mã của bạn sẽ rõ ràng hơn.
  • Java sử dụng các khối ‘try’ và ‘catch’ để xử lý các ngoại lệ. Các câu lệnh trong khối ‘try’ chặn ngoại lệ còn khối ‘catch’ xử lý ngoại lệ.
  • Các khối chứa nhiều catch có thể được sử dụng để xử lý các kiểu ngoại lệ khác nhau
    theo cách khác nhau.
  • Từ khoá ‘throw’ liệt kê các ngoại lệ mà phương thức chặn.
  • Từ khoá ‘throw’ chỉ ra một ngoại lệ vừa xuất hiện.
  • Khối ‘finally’ khai báo các câu lệnh trả về nguồn tài nguyên cho hệ thống và in những câu thông báo.
Advertisements