Bai 10 Ngoai le va xu ly ngoai le 1 Bài 10 Ngoại lệ và xử lý ngoại lệ 1 1 Mục tiêu của bài học v Giải thích về ngoại lệ là gì và mô tả các lợi ích của việc xử lý ngoại lệ hướng đối tượng v Giải thích.
Mục tiêu học v Giải thích ngoại lệ mơ tả lợi ích việc xử lý ngoại lệ hướng đối tượng v Giải thích mơ hình xử lý ngoại lệ v Sử dụng khối try/catch/finally để bắt xử lý ngoại lệ Java v Hiểu biết cách sử dụng ủy nhiệm ngoại lệ v Biết cách tạo sử dụng ngoại lệ tự định nghĩa Bài 10 Ngoại lệ xử lý ngoại lệ 1 2 Nội dung Nội dung Ngoại lệ Bắt xử lý ngoại lệ Ủy nhiệm ngoại lệ Tạo ngoại lệ tự định nghĩa Ngoại lệ Bắt xử lý ngoại lệ Ủy nhiệm ngoại lệ Tạo ngoại lệ tự định nghĩa 3 4 1.1 Ngoại lệ gì? 1.1 Ngoại lệ gì? (2) v Exception = Exceptional event v Định nghĩa: Ngoại lệ kiện xảy q trình thực thi chương trình, phá vỡ luồng bình thường chương trình v Ngoại lệ lỗi đặc biệt v Khi xảy ngoại lệ, khơng xử lý chương trình kết thúc trả lại quyền điều khiển cho hệ điều hành ERROR !! Ví dụ: 5 6 1.2 Cách xử lý lỗi truyền thống Ví dụ v Viết mã xử lý nơi phát sinh lỗi int devide(int num, int denom, int *error) { if (denom != 0){ error = 0; return num/denom; } else { error = 1; return 0; } } § Làm cho chương trình trở nên rối § Khơng phải lúc đầy đủ thơng >n để xử lý § Khơng thiết phải xử lý v Truyền trạng thái lên mức § Thông qua tham số, giá trị trả lại biến tổng thể (flag) § Dễ nhầm § Vẫn cịn khó hiểu 7 8 Nhược điểm Nội dung v Khó kiểm sốt hết trường hợp Ngoại lệ Bắt xử lý ngoại lệ Ủy nhiệm ngoại lệ Tạo ngoại lệ tự định nghĩa § Lỗi số học, lỗi nhớ,… v Lập trình viên thường qn khơng xử lý lỗi § Bản chất người § Thiếu kinh nghiệm, cố ?nh bỏ qua 9 10 10 2.1 Mục đích xử lý ngoại lệ 2.1 Mục đích xử lý ngoại lệ (2) v Giúp chương trình đáng ,n cậy hơn, tránh kết thúc bất thường v Khi xảy ngoại lệ, khơng có chế xử lý thích hợp: v Tách biệt khối lệnh gây ngoại lệ khối lệnh xử lý ngoại lệ ………… IF B IS ZERO GO TO ERROR C = A/B PRINT C GO TO EXIT ERROR: DISPLAY “DIVISION BY ZERO” § Chương trình bị ngắt ngoại lệ xảy § Các tài ngun khơng giải phóng Lãng phí v Ví dụ: Vào/ra tệp gn § Nếu ngoại lệ xảy (ví dụ chuyển đổi kiểu khơng đúng) Chương trình kết thúc mà khơng đóng tệp >n lại • Tệp %n khơng thể truy cập/hỏng • Tài ngun cấp phát khơng giải phóng Khối xử lý lỗi EXIT: END 11 12 12 2.2 Mơ hình xử lý ngoại lệ 2.2 Mơ hình xử lý ngoại lệ (2) v Hướng đối tượng v Ngoại lệ cần phải xử lý phương thức sinh ngoại lệ ủy nhiệm cho phương thức gọi đến § Đóng gói điều kiện khơng mong đợi đối tượng § Khi xảy ngoại lệ, đối tượng tương ứng với ngoại lệ tạo chứa thơng ,n chi ,ết ngoại lệ § Cung cấp chế hiệu việc xử lý lỗi § Tách biệt luồng điều khiển bất thường với luồng bình thường 13 13 14 14 2.3 Xử lý ngoại lệ Java (2) 2.3 Xử lý ngoại lệ Java v Các từ khóa § try § catch § finally v Java có chế xử lý ngoại lệ mạnh v Xử lý ngoại lệ Java thực theo mơ hình hướng đối tượng: § throw § throws § Tất ngoại lệ thể lớp kế thừa từ lớp Throwable lớp § Các đối tượng có nhiệm vụ chuyển thơng >n ngoại lệ (loại trạng thái chương trình) từ vị trí xảy ngoại lệ đến nơi quản lý/xử lý 15 15 16 16 2.3.1 Khối try/catch Ví dụ khơng xử lý ngoại lệ v Khối try catch: Phân tách đoạn chương trình thơng thường phần xử lý ngoại lệ class NoException { public static void main(String args[]) { § try {…}: Khối lệnh có khả gây ngoại lệ § catch() {…}: Bắt xử lý với ngoại lệ String text = args[0]; System.out.println(text); try { } // Doan ma co the gay ngoai le } } catch (ExceptionType e) { // Xu ly ngoai le } v ExceptionType lớp Throwable 17 17 18 18 Ví dụ có xử lý ngoại lệ Ví dụ chia cho public class ChiaCho0Demo { public static void main(String args[]){ try { int num = calculate(9,0); System.out.println(num); } catch(Exception e) { System.err.println("Co loi xay ra: " + e.toString()); } } static int calculate(int no, int no1){ int num = no / no1; return num; } } class ArgExceptionDemo { public static void main(String args[]) { try { String text = args[0]; System.out.println(text); } catch(Exception e) { System.out.println(“Hay nhap tham so chay!"); } } } 19 19 20 20 a Lớp Throwable 2.3.2 Cây phân cấp ngoại lệ Java Error lỗi đặc biệt nghiêm trọng, lỗi chương trình khơng thể quản lý Object VD: VirtualMachineError OutOfMemoryError Throwable lớp Exception cung lớp cơcấp sở sở, cho tấtdiện thể giao vàlỗi sựcó thực kiểm thi chosoát hầuđược hết VD: ArithmeticException, ngoại lệ BufferOverflowException Throwable Error v Một biến kiểu String để lưu thông gn chi gết ngoại lệ xảy v Một số phương thức § new Throwable(String s): Tạo ngoại lệ với thông tin ngoại lệ s § String getMessage(): Lấy thơng ,n ngoại lệ § void printStackTrace(): In tất thông ,n liên quan đến ngoại lệ (tên, loại, vị trí ) § … Exception RuntimeException 21 21 22 22 b Lớp Error public class StckExceptionDemo { public static void main(String args[]){ try { int num = calculate(9,0); System.out.println(num); } catch(Exception e) { System.err.println(“Co loi xay :" + e.getMessage()); e.printStackTrace(); } } static int calculate(int no, int no1) { int num = no / no1; return num; } } v Gồm ngoại lệ nghiêm trọng khơng thể kiểm tra (unchecked excep=on) xảy nhiều phần chương trình v Cịn gọi ngoại lệ phục hồi (un-recoverable excep=on) v Không cần kiểm tra mã nguồn Java bạn v Các lớp con: § VirtualMachineError: InternalError, OutOfMemoryError, StackOverflowError, UnknownError Đ ThreadDeath Đ LinkageError: Đ ã Incompa(bleClassChangeError ã AbstractMethodError, Instan(a(onError, NoSuchFieldError, NoSuchMethodError… • … 23 23 24 c Lớp Exception Một số lớp Exception v ClassNotFoundExcepOon, SQLExcepOon v java.io.IOExcepOon: v Chứa loại ngoại lệ nên/phải bắt xử lý ủy nhiệm v Người dùng tạo ngoại lệ riêng cách kế thừa từ ExcepOon v RunOmeExcepOon “tung” trình JVM thực § FileNotFoundExcep>on, EOFExcep>on… v RunOmeExcepOon: § NullPointerExcep>on, BufferOverflowExcep>on § ClassCastExcep>on, Arithme>cExcep>on Đ IndexOutOfBoundsExcep>on: ã ArrayIndexOutOfBoundsExcep%on, ã StringIndexOutOfBoundsExcep%on Đ IllegalArgumentExcep>on: Đ Khơng bắt buộc phải bắt ngoại lệ dù xảy lỗi § Khơng nên viết ngoại lệ riêng kế thừa từ lớp • NumberFormatExcep%on, InvalidParameterExcep%on… § … 25 25 26 26 2.3.3 Khối try – catch lồng Ví dụ IOException v Những phần nhỏ khối mã sinh lỗi, toàn khối lại sinh lỗi khác Cần có xử lý ngoại lệ lồng v Khi khối try lồng nhau, khối try bên thực trước import java.io.InputStreamReader; import java.io.IOException; public class HelloWorld{ public static void main(String[] args) { InputStreamReader isr = new InputStreamReader(System.in); try { System.out.print("Nhap vao ky tu: "); char c = (char) isr.read(); System.out.println("Ky tu vua nhap: " + c); }catch(IOException ioe) { ioe.printStackTrace(); } } } try { // Doan ma co the gay IOException try { // Doan ma co the gay NumberFormatException } catch (NumberFormatException e1) { // Xu ly loi sai dinh dang so } } catch (IOException e2) { // Xu ly loi vao } 27 27 28 28 2.3.4 Nhiều khối catch vExceptionType1 phải lớp ngang hàng với ExceptionType2 (trong phân cấp kế thừa) v Một đoạn mã gây nhiều ngoại lệ Sử dụng nhiều khối catch try { class MultipleCatch1 { public static void main(String args[]) { try { String num = args[0]; int numValue = Integer.parseInt(num); System.out.println("Dien tich hv la: " + numValue * numValue); } catch(Exception e1) { System.out.println("Hay nhap canh cua hv!"); } catch(NumberFormatException e2){ System.out.println("Not a number!"); } } D:\exception java.lang.NumberFormatException has already been } Lỗi caught // Doan ma co the gay nhieu ngoai le } catch (ExceptionType1 e1) { // Xu ly ngoai le } catch (ExceptionType2 e2) { // Xu ly ngoai le } v ExceptionType1 phải lớp ngang hàng với ExceptionType2 (trong phân cấp kế thừa) 29 29 30 vExceptionType1 phải lớp ngang hàng với ExceptionType2 (trong phân cấp kế thừa) class MultipleCatch1 { public static void main(String args[]) { try { String num = args[0]; int numValue = Integer.parseInt(num); System.out.println("Dien tich hv la: " + numValue * numValue); } catch(ArrayIndexOutOfBoundsException e1) { System.out.println(“Hay nhap canh cua hv!"); } catch(NumberFormatException e2){ System.out.println(“Hay nhap so!"); } } 31 } 31 30 class MultiCatch2 { public static void main( String args[]) { try { // format a number // read a file // something else } catch(IOException e) { System.out.println("I/O error "+e.getMessage(); } catch(NumberFormatException e) { System.out.println("Bad data "+e.getMessage(); } catch(Throwable e) { // catch all System.out.println("error: " + e.getMessage();} } } } 32 32 2.3.5 Khối finally public void openFile(){ try { // constructor may throw FileNotFoundException FileReader reader = new FileReader("someFile"); int i=0; while(i != -1) { //reader.read() may throw IOException i = reader.read(); System.out.println((char) i ); } reader.close(); System.out.println(" - File End -"); } catch (FileNotFoundException e) { //do something clever with the exception } catch (IOException e) { //do something clever with the exception } } 33 33 v Đảm bảo thực tất công việc cần thiết có ngoại lệ xảy § Đóng file, đóng socket, connection § Giải phóng tài ngun (nếu cần) v Chắc chắn thực dù ngoại lệ có xảy hay khơng No exception finally try block Exception catch block finally 34 34 Cú pháp try catch finally class StrExceptionDemo { static String str; public static void main(String s[]) { try { System.out.println(“Truoc ngoai le"); staticLengthmethod(); System.out.println(“Sau ngoai le"); } catch(NullPointerException ne) { System.out.println(“Da xay loi"); } finally { System.out.println(“Trong finally"); } } try { // Khoi lenh co the sinh ngoai le } catch(ExceptionType e) { // Bat va xu ly ngoai le } finally { /* Thuc hien cac cong viec can thiet du ngoai le co xay hay khong */ } v Nếu có khối try bắt buộc phải có khối catch khối finally hai static void staticLengthmethod() { System.out.println(str.length()); } } 35 35 36 36 Nội dung public void openFile(){ try { // constructor may throw FileNotFoundException FileReader reader = new FileReader("someFile"); int i=0; while(i != -1) { //reader.read() may throw IOException i = reader.read(); System.out.println((char) i ); } } catch (FileNotFoundException e) { //do something clever with the exception } catch (IOException e) { //do something clever with the exception } finally { reader.close(); System.out.println(" - File End -"); } } Ngoại lệ Bắt xử lý ngoại lệ Ủy nhiệm ngoại lệ Tạo ngoại lệ tự định nghĩa 37 37 38 38 Hai cách làm việc với ngoại lệ 3.1 Ủy nhiệm ngoại lệ v Xử lý v Phương thức ủy nhiệm ngoại lệ cho vị trí gọi cách: § Sử dụng khối try catch (finally cần) § Sử dụng throws Excep>onType phần khai báo phương thức để báo hiệu cho vị trí gọi biết phát sinh ngoại lệ ExceptionType § Sử dụng throw để tung ngoại lệ kiểu ExceptionType thân phương thức cần v Ủy nhiệm cho vị trí gọi nó: § § Nếu khơng muốn xử lý Sử dụng throw throws v Ví dụ public void myMethod(int param) throws Exception{ if (param < 10) { throw new Exception("Too low!"); } //Blah, Blah, Blah } 39 39 40 40 10 3.1 Ủy nhiệm ngoại lệ (2) 3.1 Ủy nhiệm ngoại lệ (3) v Nếu phương thức có chứa câu lệnh tung ngoại lệ (throw) phần khai báo phương thức phải khai báo có tung ngoại lệ lớp cha ngoại lệ v Phương thức khơng cần phải khai báo tung RunOmeExcepOon ngoại lệ mặc định ủy nhiệm cho JVM v Ví dụ class Test { public void myMethod(int param) { if (param < 10) { throw new RuntimeException("Too low!"); } //Blah, Blah, Blah } } § Khơng lỗi public void myMethod(int param) { if (param < 10) { throw new Exception("Too low!"); } //Blah, Blah, Blah } unreported excep,on java.lang.Excep,on; must be caught or declared to be thrown 41 41 42 42 public class DelegateExceptionDemo { public static void main(String args[]){ int num = calculate(9,3); System.out.println(“Lan 1: ” + num); num = calculate(9,0); System.out.println(“Lan 2: ” + num); } static int calculate(int no, int no1) throws ArithmeticException { if (no1 == 0) throw new ArithmeticException("Khong the chia cho 0!"); int num = no / no1; return num; } } 3.1 Ủy nhiệm ngoại lệ (3) v Tại vị trí gọi phương thức có ủy nhiệm ngoại lệ (trừ RunOmeExcepOon): § Hoặc phương thức chứa vị trí phải ủy nhiệm tiếp cho vị trí gọi § Hoặc ví trí gọi phải bắt ngoại lệ ủy nhiệm (hoặc lớp cha) xử lý try catch (finally cần) Run 43 43 44 44 11 public class DelegateExceptionDemo { public static void main(String args[]){ int num = calculate(9,3); public class DelegateExceptionDemo { public static void main(String args[]){ try { int num = calculate(9,3); System.out.println(“Lan 1: ” + num); num = calculate(9,0); System.out.println(“Lan 2: ” + num); } catch(Exception e) { System.out.println(e.getMessage()); } } static int calculate(int no, int no1) throws ArithmeticException { if (no1 == 0) throw new ArithmeticException("Khong the chia cho 0!"); int num = no / no1; return num; } } System.out.println(“Lan 1: ” + num); num = calculate(9,0); System.out.println(“Lan 2: ” + num); } static int calculate(int no, int no1) throws Exception { if (no1 == 0) throw new return num; } Compile ArithmeticException("Khong the chia cho 0!"); int num = no / no1; } G:\Java Example\DelegateExceptionDemo.java:3: unreported exception java.lang.Exception; must be caught or declared to be thrown int num = calculate(9,3); ^ G:\Java Example\DelegateExceptionDemo.java:5: unreported exception java.lang.Exception; must be caught or declared to be thrown 45 num = calculate(9,0); 45 46 46 3.1 Ủy nhiệm ngoại lệ (4) 3.2 Lan truyền ngoại lệ v Một phương thức ủy nhiệm nhiều ngoại lệ v Tình huống: § Giả sử main() gọi phương thức A(), A() gọi B(), B() gọi C() Khi ngăn xếp phương thức tạo § Giả sử C() xảy ngoại lệ public void myMethod(int tuoi, String ten) throws ArithmeticException, NullPointerException{ if (tuoi < 18) { throw new ArithmeticException(“Chua du tuoi!"); } if (ten == null) { throw new NullPointerException(“Thieu ten!"); } //Blah, Blah, Blah } 47 47 48 48 12 3.3 Kế thừa ủy nhiệm ngoại lệ 3.2 Lan truyền ngoại lệ (2) C() B() A() main() v Khi override phương thức lớp cha, phương thức lớp không phép tung ngoại lệ C() tung ngoại lệ B() A() main() v Phương thức ghi đè lớp phép tung ngoại lệ giống lớp tập ngoại lệ tung lớp cha v Nếu C() gặp lỗi tung ngoại lệ C() lại khơng xử lý ngoại lệ này, cịn nơi xử lý nơi mà C() gọi, phương thức B() v Nếu B() khơng xử lý phải xử lý ngoại lệ A()… Quá trình gọi lan truyền ngoại lệ v Nếu đến main() khơng xử lý ngoại lệ tung từ C() chương trình phải dừng lại 49 49 50 50 3.4 Ưu điểm ủy nhiệm ngoại lệ 3.3 Kế thừa ủy nhiệm ngoại lệ (2) v Dễ sử dụng class Disk { void readFile() throws EOFException {} } class FloppyDisk extends Disk { void readFile() throws IOException {} // ERROR! } § Làm chương trình dễ đọc an tồn § Dễ dàng chuyển điều khiển đến nơi có khả xử lý ngoại lệ § Có thể ném nhiều loại ngoại lệ v Tách xử lý ngoại lệ khỏi đoạn mã thông thường v Không bỏ sót ngoại lệ (ném tự động) v Gom nhóm phân loại ngoại lệ v KL: Làm chương trình dễ đọc an toàn class Disk { void readFile() throws IOException {} } class FloppyDisk extends Disk { void readFile() throws EOFException {} //OK } 51 51 52 52 13 Nội dung Tạo ngoại lệ tự định nghĩa Ngoại lệ Bắt xử lý ngoại lệ Ủy nhiệm ngoại lệ Tạo ngoại lệ tự định nghĩa v Các ngoại lệ hệ thống xây dựng khơng đủ để kiểm sốt tất lỗi Cần phải có lớp ngoại lệ người dùng định nghĩa § Kế thừa từ lớp Exception lớp § Có tất phương thức lớp Throwable public class MyException extends Exception { public MyException(String msg) { super(msg); } public MyException(String msg, Throwable cause){ super(msg, cause); } } 53 53 54 54 Sử dụng ngoại lệ người dùng định nghĩa Sử dụng ngoại lệ người dùng định nghĩa Khai báo khả tung ngoại lệ v Bắt xử lý ngoại lệ 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"); } } 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()); } } } Tung ngoại lệ 55 55 56 56 14 Tổng kết Tổng kết (2) v Bất có lỗi xảy thực chương trình ngoại lệ xuất v Mọi ngoại lệ đề phải xử lý khơng muốn chương trình kết thúc cách bất thường v Xử lý ngoại lệ cho phép kết hợp xử lý lỗi nơi v Java sử dụng khối try/catch để quản lý ngoại lệ v Các câu lệnh khối try tung ngoại lệ, việc xử lý ngoại lệ diễn khối catch v Nhiều khối catch sử dụng để xử lý tách biệt loại ngoại lệ khác v Từ khóa throws sử dụng để liệt kê danh sách ngoại lệ mà phương thức tung v Từ khóa throw sử dụng để tung ngoại lệ v Khối finally để thực công việc cần thiết dù có ngoại lệ xảy hay khơng 57 58 57 58 Bài tập v Hệ thống liên tục nhận giá trị đầu vào xâu đại diện cho số nguyên, yêu cầu lần nhận số tính trung bình cộng giá trị nhận v Xây dựng phương thức: Bài tập § public double getAverage(string x) với thuộc tính average, N có sẵn lớp v Hãy cài đặt phương thức có xử lý ngoại lệ xảy ra: § Xâu đầu vào xâu rỗng § Xâu đầu vào khơng phải số § Xâu đầu vào số nguyên 59 59 60 60 60 15 Bài tập Bài tập v Hệ thống cần đọc file để lấy dãy số (mỗi dòng số nguyên) v Hệ thống cần đọc file đầu vào để lấy dãy số (mỗi dịng số ngun), sau tách thành phần ghi file khác § Dịng file số lượng số có file § Mỗi dịng số ngun § Dịng file đầu vào số lượng số có file Mỗi dịng sau số ngun § Xây dựng phương thức phân tách dãy số: v Xây dựng phương thức c dóy s: Đ public void readListIntegers(String fileName) ã public void splitListIntegers(String fileName) v Hãy xử lý ngoại lệ: § § § § Xâu tên file xâu rỗng Khơng tìm thấy file Khơng mở file Các xâu dịng file khơng phải đại diện cho số 61 61 v Hãy xử lý ngoại lệ: Xâu tên file xâu rỗng Khơng tìm thấy file Không mở file Các xâu dịng file khơng phải đại diện cho số § Khơng ghi file § § § § 62 61 62 62 16 ... -"); } } Ngoại lệ Bắt xử lý ngoại lệ Ủy nhiệm ngoại lệ Tạo ngoại lệ tự định nghĩa 37 37 38 38 Hai cách làm việc với ngoại lệ 3.1 Ủy nhiệm ngoại lệ v Xử lý v Phương thức ủy nhiệm ngoại lệ cho vị... dung Tạo ngoại lệ tự định nghĩa Ngoại lệ Bắt xử lý ngoại lệ Ủy nhiệm ngoại lệ Tạo ngoại lệ tự định nghĩa v Các ngoại lệ hệ thống xây dựng khơng đủ để kiểm sốt tất lỗi Cần phải có lớp ngoại lệ người... ngoại lệ giống lớp tập ngoại lệ tung lớp cha v Nếu C() gặp lỗi tung ngoại lệ C() lại không xử lý ngoại lệ này, cịn nơi xử lý nơi mà C() gọi, phương thức B() v Nếu B() khơng xử lý phải xử lý ngoại