Bài giảng Xử lý biệt lệ

Các loại lỗi của chương trình  Cấu trúc các lớp quản lý lỗi của Java.  Bẫy lỗi bằng try.catch.finally  Lan truyền lỗi  Xuất Exception  Tựđịnh nghĩa Exception

pdf15 trang | Chia sẻ: haohao89 | Lượt xem: 2122 | Lượt tải: 1download
Bạn đang xem nội dung tài liệu Bài giảng Xử lý biệt lệ, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
1XỬ LÝ BIỆT LỆ (Handling Exception) 2 Mục tiêu  Giải thích được lỗi cú pháp và lỗi thực thi chương trình.  Giải thích được mô hình đối tượng Exception của Java.  Giải thích được cú pháp bẫy lỗi bằng try...catch... finally.  Sử dụng được throw và throws trong code,  Tự định nghĩa được Exception. 3 Nội dung  Các loại lỗi của chương trình  Cấu trúc các lớp quản lý lỗi của Java.  Bẫy lỗi bằng try...catch...finally  Lan truyền lỗi  Xuất Exception  Tự định nghĩa Exception 4 Các loại lỗi của chương trình Bài toán Code Chương trình Hiện thực Compile Run Syntax error No Syntax error Correct resultEND BEGIN Run-time error ( Exception ) Wrong result ? 5 Các loại lỗi của chương trình  Compile-time error = Syntax error  Run-time error = Exception, tình huống bất bình thường đã xẩy ra trong khi chương trình thực thi.  Khi có Exception:  Có thể là máy bị treo (halt).  Chương trình ngắt đột ngột, điều khiển trả về cho OS, OS thu hồi bộ nhớ của chương trình ( đuổi ra ngoài ).  Cần có cơ chế điều khiển tình huống này. 6 Giới thiệu về biệt lệ  Là một kiểu lỗi đặc biệt, nó xảy ra trong thời gian thực thi đoạn lệnh  Thông thường các điều kiện thực thi chương trình gây ra biệt lệ  Khi một biệt lệ xuất hiện, thì việc thực thi chương trình có thể kết thúc đột ngột và trả quyền điều khiển chương trình cho hệ thống.  Vài biệt lệ: người sử dụng nhập vào dữ liệu không hợp lệ, không tìm thấy file cần mở, kết nối mạng bị đứt khi giao tiếp, hoặc JVM vượt quá bộ nhớ… ERROR !! Ví dụ : 7Zero.java public class Zero { public static void main (String[] args) { int tu = 10; int mau = 0; System.out.println (tu / mau); System.out.println ("This text will not be printed."); } } ERROR 8 ArrayDemo.java public class ArrayDemo { public static void main (String[] args) { int[] codes = new int[10]; for (int i=0; i <= 10; i++) codes[i] = codes[i] * 2; System.out.println ("This text will not be printed."); } } 9 Xử lý biệt lệ Mục đích của việc xử lý biệt lệ là làm giảm thiểu việc kết thúc bất thường của hệ thống và của chương trình.  Ví dụ, thao tác xuất/nhập trong một tập tin, nếu việc chuyển đổi kiểu dữ liệu không thực hiện đúng, một biệt lệ sẽ xảy ra và chương trình bị hủy mà không đóng tập tin. Lúc đó tập tin sẽ bị hư hại và các nguồn tài nguyên được cập phát cho tập tin không được thu hồi lại cho hệ thống. Một chương trình có thể xử lý một biệt lệ trong 3 cách:  Bỏ qua  Xử lý biệt lệ tại nơi biệt lệ xuất hiện  Xử lý biệt lệ tại một phần khác trong chương trình  Trong một chương trình, nếu một biệt lệ được bỏ qua, chương trình sẽ kết thúc bất thượng và đưa ra thông báo lỗi tương ứng 10 Xử lý biệt lệ  Khi một biệt lệ xảy ra, đối tượng tương ứng với biệt lệ đó sẽ được tạo ra.  Đối tượng này sau đó được truyền tới phương thức nơi mà biệt lệ xảy ra.  Đối tượng này chứa các thông tin chi tiết về biệt lệ. Thông tin này có thể nhận được và xử lý.  Lớp ’throwable’ mà Java cung cấp là lớp trên nhất của lớp biệt lệ. 11 Cấu trúc các lớp quản lý lỗi của Java  Java là ngôn ngữ mạnh (robust) nên có các hỗ trợ giúp tối thiểu hóa các exception.  Khi có run-time error, thông tin về lỗi này được máy ảo tự động phát ra thông qua một đối tượng Exception. Đây là đối tượng được phát sinh động (dynamic thrown object) từ máy ảo, Đối tượng này có thể bẫy từ chương trình nhờ cơ chế giao tiếp giữa máy ảo và chương trình.  Java cung cấp một tập rất nhiều các lớp mô tả các lỗi cùng với cơ chế bẫy lỗi giúp developer có thể quản lý các exception trong code của chương trình.  Gói java.lang định nghĩa rất nhiều lớp lỗi run-time.  Tham khảo Java Documentation. 12 Cấu trúc các class quản lý lỗi của Java Object Throwable ExceptionError AWTError ThreadDead … SQLException ClassNotFoundException … RuntimeException ArithmeticException NullPointerException NumberFormatExceptionKhi 1 error/exception xảy ra, ta nói rằng nó bị “thrown” (throw) … 13 Lớp Throwable  Các lớp Exception đều được dẫn ra từ lớp này.  Chứa các hành vi giúp truy xuất thông tin về lỗi như:  nội dung mô tả lỗi : getMesage(), toString()  nội dung stack lúc gây lỗi: getStackTrace(), printStackTrace(),  .... 14 Một số lớp quản lý lỗi của Java class Giải thích Exception Lớp nền của các run-time error RuntimeException Lớp nền của nhiều lớp run-time error ArithmeticException Lỗi do thực thi một phép toán IllegalArgumentException Lỗi sai đối số của hàm ArrayIndexOutOfBoundsException Lỗi do chỉ số ngoài tầm của mảng NullPointerException Lỗi do truy xuất một đối tượng mà chưa khởi tạo SecurityException Lỗi do truy xuất bị cấm ClassNotFoundException Lỗi do không tìm thấy file.class 15 Một số lớp quản lý lỗi của Java class Giải thích NumberFormatException Lỗi do không đúng dạng số IOException Lỗi xuất nhập FileNotFoundException Lỗi do không tìm thấy file EOFException Lỗi do cố truy xuất nội dung 1 file khi đã ở cuối file IllegalAccessException Lỗi do truy xuất 1 class bị cấm NoSuchMethodException Lỗi do viết sai tên hành vi InterruptedException Lỗi do ngắt ngang 1 luồng lệnh đang được thực thi 16 Mô hình xử lý biệt lệ  Mô hình được biết đến là mô hình ‘catch and throw’  Khi một lỗi xảy ra, biệt lệ sẽ đuợc chặn và được đưa vào một khối.  Từ khóa để xử lý biệt lệ:  try  catch  throw  throws  finally 17 Bẫy lỗi bằng try...catch...finally  Để chương trình vẫn có thể tiếp tục hoạt động, người lập trình cần phải dự đoán lỗi có thể xẩy ra để bẫy lỗi.  Bẫy lỗi bằng cú pháp: try...catch ...finally ... try { } catch ( Exception1 e1) { } catch ( Exception2 e2) { } finally { } // Buộc phải có {...} dù chỉ có 1 phát biểu 18 Bẫy lỗi bằng try...catch...finally  Dự đoán lỗi:  Tại một thời điểm, developer có thể dự đoán chính xác các lỗi có thể xảy ra. Ví dụ: Nhập dữ liệu từ bàn phím vào 1 số thông qua hộp thoại, có 2 tình huống: người dùng không nhập (user cancel), người dùng nhập chữ.  Có thể tổng quát hoá các lỗi nhờ lớp cha (Exception) để quản lý chung. 19 Khối lệnh ‘try’ và ‘catch’ Blocks (tt)  Để bắt bất kỳ loại biệt lệ nào, ta phải chỉ ra kiểu biệt lệ là ‘Exception’ catch(Exception e)  Khi biệt lệ bị bắt không biết thuộc kiểu nào, chúng ta có thể sử dụng lớp ‘Exception’ để bắt biệt lệ đó.  Lỗi sẽ được truyền thông qua khối lệnh ‘try catch’ cho tới khi chúng bắt gặp một ‘catch’ tham chiếu tới nó, hoặc chương trình sẽ bị kết thúc 20 Zero.java public class Zero { public static void main (String[] args) { try{ int tu = 10; int mau = 0; System.out.println (tu / mau); System.out.println ("This text will not be printed."); } catch (ArithmeticException e1){ System.out.println (“Không thể chia cho 0”); } catch (Exception e2){ System.out.println (“Lỗi ngoại lệ”); } } } 21 ArrayDemo.java public class ArrayDemo { public static void main (String[] args) { try { int[] codes = new int[10]; for (int i=0; i <= 10; i++) codes[i] = codes[i] * 2; System.out.println ("This text will not be printed."); } catch (ArrayIndexOutOfBoundsException ex1) { System.out.println (“Chỉ số truy xuất vượt quá kích thước mảng”); } catch (Exception ex2) { System.out.println (“Lỗi ngoại lệ”); } } } 22 Khối ‘finally’ (tt)  Là tùy chọn không bắt buộc  Được đặt sau khối ‘catch’  Khối ‘finally’ bảo đảm lúc nào cũng được thực hiện bất chấp biệt lệ có xảy ra hay không.  Nếu không có biệt lệ nào được phát sinh, những câu lệnh trong khối finally được thực thi sau khi những câu lệnh trong khối try hoàn thành.  Nếu có biệt lệ phát sinh, những câu lệnh trong khối finally được thực thi sau khi những câu lệnh trong khối catch tương ứng hoàn thành. 23 Ví dụ import java.util.Scanner; class FinallyDemo{ public static void main (String args[]){ String name; int no1, no2; try { Scanner sc = new Scanner (System.in); name = new String("Aptech Limited"); System.out.print("Input No1: "); no1 = sc.nextInt(); System.out.print("Input No2: "); no2 = sc.nextInt(); 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(“Have good fun"); } } } 24 Bài tập  Viết chương trình cho phép nhập vào 1 số nguyên từ bàn phím. Chương trình phải được xử lý trường hợp người dùng nhập vào một số không phải số nguyên và yêu cầu nhập lại cho đến khi nhập giá trị hợp lệ thì kết thúc. 25 Các biệt lệ được định nghĩa với lệnh ‘throw’ và ‘throws’  Các biệt lệ có thể được chặn với sự trợ giúp của từ khóa ‘throw’  Từ khóa ‘throw’ chỉ ra một biệt lệ vừa xảy ra.  Exceptions được đưa ra sử dụng lệnh throw  Thông thường lệnh throw được thực hiện bên trong lệnh if để đánh giá một điều kiện xem liệu exception có được ném ra hay không if ( some problem ) throw new Exception("Informative Message" ) ;  Ví dụ của lệnh ‘throw’ try{ if (flag < 0) { throw new MyException( ) ; // user-defined } } throw exceptionReference; hoặc throw new ExceptionType(); 26 Các biệt lệ được định nghĩa với lệnh ‘throw’ và ‘throws’  Một phương thức đơn có thể chặn nhiều hơn một biệt lệ  Ví dụ từ khóa ‘throws’ xử lý nhiều biệt lệ public class Example { public void exceptionExample( ) throws ExException,LookupException { try { // statements } catch(ExException exmp) { …. } catch(LookupException lkpex) { …. } } } 27 Lan truyền lỗi  Exception propagation  Lỗi lan truyền từ trong ra cho đến khi gặp bẫy lỗi hoặc tới main và ứng dụng bị ngưng. A() B() C() D() Exception Chiều gọi hàm Chiều lan truyền lỗi catch(...) 28 Ví dụ - Propagation.java public class Propagation { public static void main (String[] args) { ExceptionScope demo = new ExceptionScope(); System.out.println("Program beginning."); demo.level1(); System.out.println("Program ending."); } } 29 ExceptionScope.java public class ExceptionScope { public void level1() { System.out.println("Level 1 beginning."); try { level2(); } catch (ArithmeticException er) { System.out.println (); System.out.println ("The exception message is: " + er.getMessage()); System.out.println (); System.out.println ("The call stack trace:"); er.printStackTrace(); System.out.println (); } System.out.println("Level 1 ending."); } public void level2() { System.out.println("Level 2 beginning."); level3 (); System.out.println("Level 2 ending."); } public void level3 () { int numerator = 10, denominator = 0; System.out.println("Level 3 beginning."); int result = numerator / denominator; System.out.println("Level 3 ending."); } } 30 Output 31 Xuất Exception  Exception thường do JVM xuất ra.  Code chương trình có thể chủ động xuất ra 1 đối tượng exception bằng từ khóa throws, throw  Mức hành vi: dùng chỉ thị throws để báo cho JVM xuất một loại Exception khi có lỗi.  Nếu là code trong hành vi thì dùng chỉ thị throw.  Khi throw trong code của thân hàm, phải yêu cầu tạo đối tượng Exception bằng toán tử new.  Đương nhiên khi chủ động xuất lỗi, chương trình sẽ ngắt ngay. 32 Xuất Exception tại khai báo method 33 Xuất Exception trong thân method gán message cho Exception 34 Tự định nghĩa Exception  Những exception đã xây dựng trước có thể không đủ để bẫy tất cả các lỗi, do đó người lập trình có thể tự định nghĩa một loại Exception dựa trên các loại Exception đã có.  Khi định nghĩa những lớp exception riêng thì tất cả các exception phải là lớp con của lớp Throwable.  Phương pháp khi khai báo một user-defined exception:  Tên lớp exception  Tên lớp cha  Thông báo lỗi. 35 myException.java public class myException extends Exception { public myException () { super ("Gia tri nhap vao khong nam trong khoang quy dinh."); } } 36 Main.java Import java.util.*; public class Main{ public static void main (String[] args) { try{ final int MIN = 25, MAX = 40; myException er = new myException(); System.out.print ("Enter an integer value between " + MIN + " and " + MAX + ", inclusive: "); Scanner sc = new Scanner(System.in); int value = sc.nextInt(); if (value MAX) throw er; else System.out.println ("Gia tri nhap hop le"); } catch (myException ex) { System.out.println (ex.getMessage()); } } } 37 UserDefinedException.java class ArraySizeException extends NegativeArraySizeException { public ArraySizeException() // constructor { super("You have passed illegal array size"); } } class UserDefinedException { int size, array[]; public UserDefinedException(int val) { size = val; try { checkSize(); } catch(ArraySizeException e) { System.out.println(e); } } void checkSize() throws ArraySizeException { if(size < 0) throw new ArraySizeException(); array = new int[3]; for(int count = 0; count < 3; count++) array[count] = count+1; } public static void main(String arg[]) { new UserDefinedException(Integer.parseInt(arg[0])); } } Output 38 LUỒNG NHẬP XUẤT (Input/Output Stream) 39 Nội dung  Tổng quan về I/O Stream  Đọc và ghi files text  Object serialization 40 Luồng nhập xuất - I/O Streams  Luồng là những đường ống dẫn cho phép gửi và nhận thông tin trong những chương trình java  Khi một luồng được đọc hoặc ghi, những tiểu trình khác bị khóa  Một IOException được đưa ra, nếu như trong khi đọc và ghi luồng xuất hiện lỗi.  Lớp ‘java.lang.System’ định nghĩa những luồng nhập xuất chuẩn.  Một stream là một dãy những byte chảy từ source (nguồn) tới destination (đích).  Trong một chương trình, chúng ta đọc thông tin từ một luồng nhập (input stream) và ghi thông tin tới luồng xuất (output stream  Đặt trong gói java.io 41 Luồng nhập xuất - I/O Streams  Input Streams – đọc dữ liệu từ nguồn như là Files, Buffers trong bộ nhớ, và các Socket  Output Streams – ghi dữ liệu xuống đích như là Files, Buffers trong bộ nhớ, và các Socket 42 Luồng nhập xuất chuẩn  Những lớp trong gói I/O chia luồng nhập xuất ra thành những loại khác nhau  Một I/O stream là một  character stream: làm việc với dữ liệu text  byte stream: làm việc với dữ liệu byte  Có 3 loại I/O streams chuẩn:  standard output – được định nghĩa bởi đối tượng System.out  standard input – được định nghĩa bởi đối tượng System.in  standard error – được định nghĩa bởi đối tượng System.err  System.out được sử dụng khi chúng ta thực thi những câu lệnh println để hiển thị kết quả trên màn hình.  System.in luồng nhập chuẩn thường được dùng để đọc các ký tự dữ liệu từ bàn phím, luồng nhập chuẩn này có thể được sử dụng nhiều lần cùng với đối tượng Scanner.  System.err là luồng lỗi chuẩn 43 Luồng nhập xuất chuẩn  Lớp System.out System.out.println(“Hello”);  Lớp I/O khai báo luồng nhập như sau: InputStreamReader isr=new InputStreamReader (System.in) BufferedReader stdin = new BufferedReader (isr);  Đối tượng InputStreamReader chuyển luồng byte gốc thành luồng ký tự.  Đối tượng BufferedReader cho phép chúng ta sử dụng phương thức readLine để lấy toàn bộ dòng nhập. 44 Streams (cont.) Đọc từ luồng 1. Mở luồng 2. Trong khi còn thông tin 3. Đọc luồng 4. Đóng luồng Ghi xuống luồng 1. Đọc luồng 2. Trong khi còn thông tin 3. Ghi luồng 4. Đóng luồng 45 Các loại luồng nhập xuất  Luồng nhập xuất dựa trên những kiểu dữ liệu Luồng ký tự • Sử dụng để đọc và ghi ký tự • Dựa trên dữ liệu 2 byte(16bits) • xử lý thông qua những luồng (Reader) đọc, (Writer) ghi. • có thể xử lý những ký tự Unicode Luồng byte • Dựa trên dữ liệu 1 byte (8 bit) • có thể được sử dụng với bất kỳ kiểu đối tượng nào • Không thể xử lý các ký tự UNICODE • Sử dụng được cho byte và luồng nhị phân • Xử lý thông qua InputStreams và OutputStreams 46 Cấu trúc phân cấp luồng nhập I/O 47 Cấu trúc phân cấp luồng nhập I/O 48 Biệt lệ (Exception) trong I/O  FileNotFoundException được đưa ra nếu như không tìm thấy file (khi constructor FileReader được thực thi)  Thao tác trên một số lớp I/O có thể đưa ra IOException  File không tồn tại.  Nếu file đã tồn tại, nhưng chương trình không thể tìm thấy nó.  File có thể không chứa kiểu dữ liệu chúng ta mong đợi.  Một IOException là một loại biệt lệ được kiểm tra. 49 Text Files  Những biến và mảng chỉ là bộ nhớ tạm thời, nó sẽ mất trong quá trình thu gom rác hoặc khi chương trình kết thúc.  File được sử dụng cho việc lưu trữ lâu dài, được gọi là dữ liệu cố định.  Thông tin có thể được đọc từ file và được ghi đến file bằng cách khai báo và sử dụng những luồng nhập xuất.  Lớp FileReader đại diện cho file nhập bao gồm dữ liệu kiểu kí tự  Lớp FileWriter đại diện cho file xuất, được sử dụng để xuất dữ liệu kí tự xuống file 50 Ghi xuống file text 1. Mở luồng 2. Ghi thông tin 3. Đóng luồng FileWriter BufferedWriter 51 Ghi xuống file text  2 constructors của lớp FileWriter hay sử dụng: FileWriter(String fileName) FileWriter(String fileName, boolean append)  Trong constructor thứ 2 có 1 tham số append. Nếu append là true thì constructor sẽ mở file đang tồn tại và cho ghi mà không hủy bỏ nội dung cũ. Nếu file không tồn tại, nó sẽ được tạo.  Lớp BufferedWriter có:  Phương thức write : cho phép ghi nội dung xuống file  Phương thức newLine : cho phép ngắt 1 dòng 52 Ghi xuống file text  Lớp FileWriter : đại diện cho file xuất, nhưng chỉ hỗ trợ thao tác trên dữ liệu nhỏ  Do đó, chúng ta dựa vào đối tượng PrintStream, và sử dụng phương thức print và println.  Chúng ta xây dựng lớp đại diện cho file xuất bằng cách kết hợp những lớp này một cách thích hợp.  Luồng xuất nên được đóng tường minh. 53 WriteFile.java import java.io.*; public class WriteFile { public static void main (String[] args) throws IOException { FileWriter fw = new FileWriter ("Lop.txt"); BufferedWriter bw = new BufferedWriter (fw); bw.write(“DHTH1 – Dai hoc Tin hoc 1"); bw.write(“DHHO1 – Dai hoc Hoa 1"); bw.write("CDTH7K - Cao dang tin hoc 7K"); bw.close(); } } 54 WriteFile.java import java.io.*; public class WriteFile { public static void main (String[] args) throws IOException { FileWriter fw = new FileWriter ("Lop.txt"); BufferedWriter bw = new BufferedWriter (fw); PrintWriter outFile = new PrintWriter (bw); outFile.println(" DHTH1 – Dai hoc Tin hoc 1 "); outFile.println(" DHHO1 – Dai hoc Hoa 1 "); outFile.println("CDTH7K - Cao dang tin hoc 7K"); outFile.close(); } } 55 Đọc từ file text 1. Mở luồng 2. Đọc thông tin 3. Đóng luồng FileReader BufferedReader 56 Đọc từ file text  Lớp BufferedReader: cung cấp phương thức readLine, phương thức này cho phép chúng ta đọc toàn bộ dòng ký tự trong 1 thao tác.  Phương thức readLine trả về một chuỗi  Phương thức readLine trả về null khi không có sẵn giá trị nhập.  Constructor cho lớp BufferedReader như sau: BufferedReader( Reader in )  Constructor cho lớp FileReader như sau: FileReader(String fileName)throws FileNotFoundException 57 ReadFile.java import java.io.*; public class ReadFile { public static void main (String[] args) { String filename = “Lop.txt“, para; try { FileReader fr = new FileReader (filename); BufferedReader br = new BufferedReader (fr); para = br.readLine(); while (para != null) { System.out.println (para); para = br.readLine(); } br.close(); } DHTH1 – Dai hoc Tin hoc 1 DHHO1 – Dai hoc Hoa 1 CDTH7K - Cao dang tin hoc 7K Lop.txt catch (FileNotFoundException exception) { System.out.println ("The file " + filename + " was not found."); } catch (IOException exception) { System.out.println (exception); } } } 58 Đọc – Ghi file text (Unicode) 1. Mở luồng 2. Đọc thông tin 3. Đóng luồng FileInputStream InputStreamReader BufferedReader 1. Mở luồng 2. Ghi thông tin 3. Đóng luồng FileOutputStream OutputStreamWriter BufferedWriter Ghi Đọc 59 WriteFile_Uni.java (Unicode) import java.io.*; public class WriteFile_Uni { public static void ma