- Định nghĩa 1 ngoại lệ - Hiểu được mục đích của việc xử lý ngoại lệ - Hiểu được các kiểu ngoại lệ trong Java - Mô tả mô hình xử lý ngoại lệ - Hiểu được các khối lệnh chứa nhiều catch - Mô tả cách sử dụng các khối try, catch, và finally
Chương Xử lý ngoại lệ (Exception Handling) Sau kết thúc chương này, bạn nắm nội dung sau: Định nghóa ngoại lệ (exception) Hiểu mục đích việc xử lý ngoại lệ Hiểu kiểu ngoại lệ khác Java Mô tả mô hình xử lý ngoại lệ Hiểu khối lệnh chứa nhiều catch Mô tả cách sử dụng khối ‘try’, ‘catch’ ‘finally’ Giải thích cách sử dụng từ khoá ‘throw’ ‘throws’ Tự tạo ngoại lệ 7.1 Giới thiệu Exception lỗi đặc biệt Lỗi xuất 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 thi hành chương trình tạo exception Những trạng thái trước ta xây dựng chương trình Nếu bạn không phân phối trạng thái exception bị kết thúc đột ngột Ví dụ, việc chia cho tạo lỗi chương trình Ngôn ngữ Java cung cấp máy dùng để xử lý ngoại lệ tuyệt vời Việc xử lý làm hạn chế tối đa trường hợp hệ thống bị phá vỡ (crash) hay hệ thống bị ngắt đột ngột Tính làm cho Java ngôn ngữ lập trình mạnh 7.2 Mục đích việc xử lý ngoại lệ Một chương trình nên có chế xử lý ngoại lệ thích hợp Nếu không, chương trình bị ngắt exception xảy Trong trường hợp đó, tất nguồn tài nguyên mà hệ thống trước phân phối di dời trạng thái Điều gây lãng phí tài nguyên Để tránh trường hợp này, tất nguồn tài nguyên mà hệ thống phân phối nên thu hồi lại Tiến trình đòi hỏi chế xử lý ngoại lệ thích hợp Cho ví dụ, xét thao tác nhập xuất (I/O) tập tin Nếu việc chuyển đổi kiểu liệu không thực đúng, ngoại lệ xảy chương trình bị hủy mà không đóng lại tập tin Lúc tập tin dễ bị hư hại nguồn tài nguyên cấp phát cho tập tin không thu hồi lại cho hệ thống 27 7.3 Xử lý ngoại lệ Khi ngoại lệ xảy ra, đối tượng tương ứng với ngoại lệ tạo Đối tượng sau truyền cho phương thức nơi mà ngoại lệ xảy Đối tượng chứa thông tin chi tiết ngoại lệ Thông tin nhận xử lý Các môi trường runtime ‘IllegalAccessException’, ‘EmptyStackException’ v.v… chặn ngoại lệ Đoạn mã chương trình tạo ngoại lệ Lớp ‘throwable’ Java cung cấp lớp lớp Exception , lớp lớp cha ngoại lệ khác 7.4 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ý hiệu ứng lề (lỗi), biết đến mô hình ‘catch throw’ Trong mô hình này, lỗi xảy ra, ngoại lệ bị chặn đưa vào khối Người lập trình viên nên xét trạng thái ngoại lệ độc lập từ việc điều khiển thông thường chương trình Các ngoại lệ phải bắt giữ không chương trình bị ngắt Ngôn ngữ Java cung cấp từ khoá sau để xử lý ngoại lệ: try catch throw throws finally Dưới cấu trúc mô hình xử lý ngoại lệ: try { // place code that is expected to throw an exception } 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 28 // 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 } 7.4.1 Các ưu điểm mô hình ‘catch throw’ Mô hình ‘catch throw’ có hai ưu điểm: Người lập trình viên phải phân phối trạng thái lỗi vào nơi cần thiết Không cần phải thực mức Một thông báo lỗi in tiến hành xử lý ngoại lệ 7.4.2 Các khối ‘try’ ‘catch’ Khối ‘try-catch’ sử dụng để thi hành mô hình ‘catch throw’ việc xử lý ngoại lệ Khối ‘try’ chứa lệnh thi hành Các ngoại lệ bị chặn thi hành câu lệnh Phương thức dùng để chặn ngoại lệ khai báo khối ‘try’ Một hay nhiều khối ‘catch’ theo sau khối ‘try’ Các khối ‘catch’ bắt ngoại lệ bị chặn khối ‘try’ Hãy nhìn khối ‘try’ đây: try { doFileProcessing(); // user-defined method displayResults(); } catch (Exception e) // exception object { System.err.println(“Error :” + e.toString()); e.printStackTrace(); } 29 Ở đây, ‘e’ đối tượng lớp ‘Exception’ Chúng ta sử dụng đối tượng để in chi tiết ngoại lệ Các phương thức ‘toString’ ‘printStackTrace’ sử dụng để mô tả exception phát sinh Hình sau kết xuất phương thức ‘printStackTrace()’ Hình 7.1 Khối Try Catch Để bắt giữ ngoại lệ nào, ta phải kiểu ngoại lệ ‘Exception’ catch(Exception e) Khi ngoại lệ bị bắt giữ thuộc kiểu nào, sử dụng lớp ‘Exception’ để bắt ngoại lệ Khối ‘catch()’ bắt giữ lỗi xảy thi hành phương thức ‘doFileProcessing’ hay ‘display’ Nếu lỗi xảy thi hành phương thức ‘doFileProcessing()’, lúc phương thức ‘displayResults()’ không gọi Sự thi hành tiếp tục thực khối ‘catch’ Để có nhiều lớp xử lý lỗi hơn, ‘LookupException’ thay đối tượng ngoại lệ chung (Exception e), lỗi thật instance ‘LookupException’ hay số lớp Lỗi truyền qua khối ‘try catch’ chúng bắt gặp ‘catch’ tham chiếu tới hay toàn chương trình phải bị huỷ bỏ 7.5 Các khối chứa nhiều Catch Các khối chứa nhiều ‘catch’ xử lý kiểu ngoại lệ khác cách độc lập Chúng liệt kê đoạn mã sau: try { doFileProcessing(); // user defined mothod displayResults(); // user defined method } 30 catch(LookupException e) // e – Lookupexception object { handleLookupException(e); // user defined handler } catch(Exception e) { System.err.println(“Error:” + e.printStackTrace()); } } Trong trường hợp này, khối ‘catch’ bắt giữ ‘LockupException’ Khối ‘catch’ thứ hai xử lý kiểu ngoại lệ khác với khối ‘catch’ thứ Một chương trình chứa khối ‘try’ lồng Ví dụ đoạn mã đây: try { statement 1; statement 2; try { statement1; statement2; } catch(Exception e) // of the inner try block { } } catch(Exception e) // of the outer try block { } … Khi sử dụng ‘try’ lồng nhau, khối ‘try’ bên thi hành Bất kỳ ngoại lệ bị chặn khối ‘try’ bị bắt giữ khối ‘catch’ theo sau Nếu khối ‘catch’ thích hợp không tìm thấy khối ‘catch’ khối ‘try’ bên xem xét Nếu không, Java Runtime Environment xử lý ngoại lệ chương trình 7.1 minh họa cách sử dụng khối ‘try’ ‘catch’ 31 Chương trình 7.1 class TryClass { public static void main(String args[]) { int demo=0; try { System.out.println(20/demo); } catch(ArithmeticException a) { System.out.println(“Cannot Divide by zero”); } } } Kết xuất chương trình: Hình 7.2 ArithmeticException Trong chương trình này, số chia cho Đây không toán tử số học hợp lệ Do ngoại lệ bị chặn bắt giữ khối catch Khi người lập trình viên nhận biết loại ngoại lệ xảy ra, hay cô ta viết câu lệnh khối ‘catch’ Ở đây, ‘a’ sử dụng đối tượng Arithmaticexception để in chi tiết toán tử ngoại lệ mà hệ thống cung cấp Nếu bạn thay lệnh ‘System.out.println’ khối ‘catch’ lệnh ‘System.out.println(a.getMessage())’ kết xuất chương trình sau: 32 Hình 7.3 Câu thông báo lỗi Khi khối ‘try’ sử dụng mà khối ‘catch’ nào, chương trình biên dịch mà không gặp cố bị ngắt thực thi Bởi ngoại lệ xảy thực thi chương trình 7.6 Khối ‘finally’ Khi ngoại lệ xuất hiện, phương thức thực thi bị dừng mà không thi hành toàn vẹn Nếu điều xảy ra, đoạn mã (ví dụ đoạn mã với chức thu hồi tài nguyên có lệnh đóng lại tập tin khai báo cuối phương thức) không gọi Java cung cấp khối ‘finally’ để giải việc Khối ‘finally’ thực tất việc thu dọn ngoại lệ xảy Khối sử dụng kết hợp với khối ‘try’ Khối ‘finally’ chứa câu lệnh thu hồi tài nguyên cho hệ thống hay lệnh in câu thông báo Các lệnh bao gồm: Đóng tập tin Đóng lại kết (được sử dụng chương trình sở liệu) Đóng lại kết nối tạo sở liệu try { doSomethingThatMightThrowAnException(); } finally { cleanup(); } Phương thức ‘cleanup()’ gọi phương thức ‘doSomethingThatMightThrowAnException()’ chặn ngoại lệ Mặt khác ‘cleanup()’ gọi ngoại lệ bị chặn thi hành tiếp tục sau khối lệnh ‘finally’ 33 Khối ‘finally’ tuỳ ý, không bắt buộc Khối đặt sau khối ‘catch’ Hệ thống duyệt từ câu lệnh khối ‘finally’ sau gặp câu lệnh ‘return’ hay lệnh ‘break’ dùng khối ‘try’ Khối ‘finally’ bảo đảm lúc thực thi, bất chấp có ngoại lệ xảy hay không Hình 7.4 minh họa thi hành khối ‘try’, ‘catch’ vaø ‘finally’ try block No Exception finally block Exception occurs catch block finally block Hình 7.4 Khối lệnh ‘try’, ‘catch’ ‘finally’ Hình 7.2 sử dụng khối ‘finally’ Ở đây, khối ‘finally’ thi hành bất chấp ‘ArithmeticException’ có xảy hay không Khối khai báo hoạt động thu dọn Chương trình 7.2 class FinallyDemo { String name; int no1,no2; FinallyDemo(String args[]) { try { 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) 34 { 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); } } Kết xuất chương trình: Hình 7.5 Khối Finally Trong ví dụ này, câu lệnh khối ‘Finally’ luôn thi hành, bất chấp ngoại lệ có xảy hay không Trong kết xuất bên trên, khối ‘finally’ thi hành ngoại lệ xảy 7.7 Các ngoại lệ định nghóa với lệnh ‘throw’ ‘throws’ Các ngoại lệ bị chặn với trợ giúp từ khoá ‘throw’ Từ khóa ‘throw’ ngoại lệ vừa xảy Toán tử throw đối tượng lớp, lớp dẫn xuất từ ‘Throwable’ Đoạn lệnh sau cách sử dụng lệnh ‘throw’: try 35 { if (flag