Chương 4: Exceptions Chương 4: Exceptions
GVLT: Trần Anh Dũng
1
Nội dung Nội dung
2
(cid:1) Giới thiệu. (cid:1) Cách xử lý lỗi truyền thống. (cid:1) Xử lý ngoại lệ (Exception) trong java (cid:1) Ưu ñiểm của “ném” bắt ngoại lệ (cid:1) Một số lớp ngoại lệ (cid:1) Kiểm soát ngoại lệ (cid:1) Ngoại lệ do người dùng tạo (cid:1) Lan truyền ngoại lệ
Giới thiệu Giới thiệu
(cid:1) Lỗi chủ quan: do lập trình sai
(cid:1) Lỗi khách quan: do dữ liệu, do trạng thái của hệ
(cid:1) Mọi ñoạn chương trình ñều tiềm ẩn khả năng sinh lỗi
(cid:1) ?
thống (cid:1) Lỗi có 2 loại.
(cid:1) Ngoại lệ (Exception): các trường hợp hoạt ñộng không
3
bình thường
Cách xử lý lỗi truyền thống Cách xử lý lỗi truyền thống
(cid:1) Làm cho chương trình trở nên khó hiểu
(cid:1) Không phải lúc nào cũng ñầy ñủ thông tin ñể xử lý
(cid:1) Không nhất thiết phải xử lý (cid:1) Truyền trạng thái lên mức trên
(cid:1) Thông qua tham số, giá trị trả lại hoặc biến tổng thể
(cid:1) Cài ñặt mã xử lý tại nơi phát sinh ra lỗi
(cid:1) Dễ nhầm
(cid:1) Khó hiểu
4
(flag)
Ví dụ (1) Ví dụ (1)
…………
IF B IS ZERO GO TO ERROR
C = A/B
PRINT C
GO TO EXIT
ERROR:
DISPLAY “DIVISION BY ZERO”
EXIT:
END
5
Block that handles error
Ví dụ (2) Ví dụ (2)
int devide(int num, int denom, int& error)
{
if (0 != denom){
error = 0; return num/denom;
} else {
error = 1;
return 0;
}
6
}
Cách xử lý lỗi truyền thống Cách xử lý lỗi truyền thống
(cid:1) Lỗi số học
(cid:1) Lỗi bộ nhớ
(cid:1) …
(cid:1) Khó kiểm soát ñược hết các trường hợp
(cid:1) Bản chất con người
(cid:1) Thiếu kinh nghiệm, cố tình bỏ qua
7
(cid:1) Lập trình viên thường quên không xử lý lỗi
Xử lý ngoại lệ trong java Xử lý ngoại lệ trong java
(cid:1) Java là ngôn ngữ mạnh, có nghĩa là tối thiểu hóa ñược
lỗi và khi có lỗi thì chúng có thể ñược quản lý.
(cid:1) Ngoại lệ ñược “ném” tự ñộng
(cid:1) Ngoại lệ ñược “ném” tường minh
(cid:1) Ngoại lệ: là ñối tượng mang thông tin về lỗi ñã xảy ra
(cid:1) Ném ngoại
(cid:1) Dựa trên cơ chế “ném” (throw) và bắt (catch) ngoại lệ
lệ: dừng chương trình và chuyển ñiều
(cid:1) Bắt ngoại lệ: xử lý với ngoại lệ
8
khiển lên mức trên (nơi bắt ngoại lệ)
Ưu ñiểm của “ném” bắt ngoại lệ Ưu ñiểm của “ném” bắt ngoại lệ
(cid:1) Dễ dàng chuyển ñiều khiển ñến nơi có khả năng xử
(cid:1) Dễ sử dụng
(cid:1) Có thể “ném” nhiều loại ngoại lệ (cid:1) Tách xử lý ngoại lệ khỏi thuật toán
(cid:1) Tách mã xử lý
(cid:1) Sử dụng cú pháp khác
lý ngoại lệ
9
(cid:1) Không bỏ sót ngoại lệ (“ném” tự ñộng) (cid:1) Chương trình dễ ñọc hơn, an toàn hơn
Hierarchy of Exception Classes Hierarchy of Exception Classes
10
Một số lớp ngoại lệ (1) Một số lớp ngoại lệ (1)
(cid:1) Có một biến String ñể lưu thông tin chi tiết về ngoại lệ
(cid:1) Lớp Throwable
ñã xảy ra
//Tạo một ngoại lệ có tên là s.
(cid:1) Một số phương thức cơ bản (cid:2) Throwable(String s); (cid:2) String getMessage(); (cid:2) void printStackTrace(); //In ra tất cả các thông tin
//Lấy thông tin về ngoại lệ
11
liên quan ñến ngoại lệ
Một số lớp ngoại lệ (2) Một số lớp ngoại lệ (2)
(cid:1) Có nhiều ngoại lệ thuộc lớp con của Exception.
(cid:1) Người dùng có thể tạo ra các ngoại
(cid:1) Lớp Exception
lệ kế thừa từ
Exception.
(cid:1) Chỉ những lỗi nghiêm trọng và không dự ñoán trước LinkageError,
(cid:1) Lớp Error
ThreadDead, như
12
ñược VirtualMachineError…
Một số lớp ngoại lệ (3) Một số lớp ngoại lệ (3)
(cid:1) RuntimeException: Chỉ các ngoại lệ có thể xảy ra khi
(cid:1) NullPointException: con trỏ null
(cid:1) OutOfMemoryException: hết bộ nhớ
(cid:1) ArithmeticException: lỗi toán học, lỗi chia không…
(cid:1) ClassCastException: lỗi ép kiểu
(cid:1) ArrayIndexOutOfBoundsException:
JVM thực thi chương trình
lỗi vượt quá chỉ
(cid:1) ...
13
số mảng
Các loại ngoại lệ Các loại ngoại lệ
(cid:1) Java phân biệt hai loại ngoại lệ là ngoại lệ cần kiểm tra
và ngoại lệ không cần kiểm tra
(cid:1) Là các ngoại lệ không bắt buộc phải kiểm tra.
(cid:1) Gồm RuntimeException, Error và các lớp con của
(cid:1) Ngoại lệ unchecked
(cid:1) Là các ngoại lệ bắt buộc phải ñược kiểm tra.
(cid:1) Gồm các ngoại lệ còn lại.
14
chúng. (cid:1) Ngoại lệ checked
Kiểm soát ngoại lệ (1) Kiểm soát ngoại lệ (1)
(cid:1) ðoạn code có thể sinh ra lỗi cần ñặt trong khối lệnh bắt ñầu bằng try.
(cid:1) ðoạn code ñể kiểm tra, xử lý trong trường hợp có lỗi xảy ra ñặt trong khối lệnh catch.
try {
// ðoạn mã có thể sinh ra lỗi …
}
catch (
// ðoạn mã kiểm soát lỗi
15
}
Kiểm soát ngoại lệ (2) Kiểm soát ngoại lệ (2)
(cid:1) Khối lệnh ñặt trong finally luôn ñược thực thi cho dù có Exception hay không. (cid:1) Thường dùng ñể giải phóng tài nguyên
try {
// ðoạn mã có thể sinh ra lỗi …
}
catch (
finally {
//ðoạn mã luôn luôn ñược thực thi
16
}
Kiểm soát ngoại lệ (3) Kiểm soát ngoại lệ (3)
try {
// Khối lệnh trước dòng lệnh sinh ra lỗi // Dòng lệnh sinh ra lỗi (Exception) //…
}
catch (
// ðoạn mã kiểm soát lỗi
Khối lệnh sau dòng lệnh sinh ra lỗi sẽ bị bỏ qua và không thực hiện khi có exception
} finally {
//…
17
}
Ví dụ (1) Kiểm soát ngoại lệ -- Ví dụ (1) Kiểm soát ngoại lệ
Ví dụ 1:
…
try {
int x = 10;
int y = 0;
float z = x/y;
System.out.print("Ket qua la:" + z);
} catch(ArithmeticException e) {
System.out.println(“Loi tinh toan so hoc”)
}
18
…
Ví dụ (2) Kiểm soát ngoại lệ -- Ví dụ (2) Kiểm soát ngoại lệ
Ví dụ 2: … void docfile(String filename) throws IOException{
… FileInputStream fin = new
FileInputStream(filename);
…
19
}
Ví dụ (3) Kiểm soát ngoại lệ -- Ví dụ (3) Kiểm soát ngoại lệ
Hoặc … void docfile(String filename) { …
try { …
FileInputStream fin = new
FileInputStream(filename);
… } catch (IOException e) {
System.out.println(“Loi doc file”);
}
20
}
Ví dụ (4) Kiểm soát ngoại lệ -- Ví dụ (4) Kiểm soát ngoại lệ
import java.io.*; public class MainClass {
public static void main(String[] args) {
try {
int num_1, num_2; BufferedReader in = new BufferedReader(new
InputStreamReader(System.in));
System.out.print("\n Nhap so thu 1:"); num_1 = Integer.parseInt(in.readLine()); System.out.print("\n Nhap so thu 2:"); num_2 = Integer.parseInt(in.readLine()); float rs = (float)num_1/num_2; System.out.print("\n Ket qua:" + rs);
}
21
Ví dụ (4) Kiểm soát ngoại lệ -- Ví dụ (4) Kiểm soát ngoại lệ
catch (ArithmeticException e) {
System.out.print("Loi chia cho 0");
} catch (IOException e) {
System.out.print("Loi xuat nhap");
} catch (Exception e) {
System.out.print("Loi khac");
} System.out.print(“Kiem soat duoc loi hay Khong co loi");
}
}
22
“Ném” ngoại lệ “Ném” ngoại lệ
(cid:1) Khi có lỗi phương thức sẽ ném ra một exception
(cid:1) Việc kiểm soát exception giúp chương trình kiểm soát ñược những trường hợp ngoại lệ và xử lý lỗi.
(cid:1) Dùng từ khóa throws ñể chỉ ñịnh những loại exception mà phương thức có thể “ném” ra.
throws 23 (cid:1) Trong khối catch, ta có thể không xử lý trực tiếp ngoại lệ mà lại “ném” lại ngoại lệ ñó cho nơi khác xử lý. catch (IOException e) { throw e; } 24 (cid:1) Chú ý: Trong trường hợp trên, phương thức chứa catch
phải bắt ngoại lệ hoặc khai báo throws cho ngoại lệ (nếu
là loại checked). (cid:1) Không ñủ thông tin ñể xử lý (cid:1) Không ñủ thẩm quyền (cid:1) Không nhất thiết phải xử lý ngoại lệ trong phương thức (cid:1) Một phương thức muốn “ném” ngoại lệ ra ngoài phải (cid:1) Có thể “ném” ngoại lệ thuộc lớp dẫn xuất của ngoại lệ khai báo việc “ném” ngoại lệ bằng từ khóa throws 25 ñược khai báo (cid:1) ðịnh nghĩa lớp ngoại lệ // file MyException.java
public class MyException extends Exception
{ public MyException(String msg)
{ super(msg); } 26 } (cid:1) Sử dụng ngoại lệ // file ExampleException.java
public class ExampleException
{ public void copy(String fileName1, String fileName2) { } 27 public static void main(String[] args)
{ ExampleException obj=new ExampleException();
try { String a = args[0];
String b = args[1];
obj.copy(a,b); } catch (MyException e) { System.out.println(e.getMessage()); } } 28 (cid:1) Sử dụng ngoại lệ import java.io.*; // ArrayCatch.java
class MyException extends ArrayIndexOutOfBoundsException{ MyException(){ super("\nChi so nam ngoai pham vi cua mang"); } }
class ArrayCatch{ int a[]= { 1,2,3,4,5}; int n=5;
public static void main(String args[]){ ArrayCatch Obj= new ArrayCatch();
Obj.OutElement(7); }
void OutElement(int i) throws MyException{ if (i<0 || i>=n) throw new MyException();
else System.out.println (a[i]); } } 29 (cid:1) Giả sử trong main() gọi phương thức A(), trong A()
gọi B(), trong B() gọi C(). Khi ñó một ngăn xếp các
phương thức ñược tạo ra. (cid:1) Giả sử trong C() xảy ra ngoại lệ. C() tung ngoại lệ C() B() B() A() A() main() main() 30 (cid:1) Tình huống: try{ try{ //… //… }
catch (EOFException e){ }
catch (IOException e){ //… //… }
catch (IOException e){ }
catch (EOFException e){ //… //… } } 31 ðúng Sai 1. Viết chương trình cho phép tính giá trị của biểu thức: A = Yêu cầu xử lý các ngoại lệ có thể xảy ra. 32 2. Viết chương trình cho phép tạo một mảng 2 chiều cỡ
mxn với m, n nhập từ bàn phím. Cài ñặt các xử lý
ngoại lệ cần thiết. 3. Xây dựng lớp ngoại lệ DateException cho các lỗi về ngày tháng. 33 4. Viết chương trình cho phép người dùng nhập vào
ngày, tháng năm, nếu thông tin này không hợp lệ sẽ
tung ra một ngoại lệ DateException, sau ñó thông báo
cho người nhập biết và cho phép người dùng nhập lại. 34“Ném” ngoại lệ
“Ném” ngoại lệ
“Ném” ngoại lệ khỏi phương thức
“Ném” ngoại lệ khỏi phương thức
Ngoại lệ do người dùng tạo (1)
Ngoại lệ do người dùng tạo (1)
Ngoại lệ do người dùng tạo (2)
Ngoại lệ do người dùng tạo (2)
Khai báo khả năng ném ngoại lệ
throws MyException
if (fileName1.equals(fileName2))
// tung ngoại lệ
throw new MyException("File trung ten");
System.out.println("Copy completed");
Ném ngoại lệ
Ngoại lệ do người dùng tạo (3)
Ngoại lệ do người dùng tạo (3)
Ngoại lệ do người dùng tạo (4)
Ngoại lệ do người dùng tạo (4)
Lan truyền ngoại lệ
Lan truyền ngoại lệ
Thừa kế và vấn ñề bắt ngoại lệ
Thừa kế và vấn ñề bắt ngoại lệ
Bài tập
Bài tập
5x - y
2x + 7y
Bài tập
Bài tập
Hỏi & ñáp
Hỏi & ñáp