Giáo trình Core Java - Chương 7: Xử lý ngoại lệ

Chương 7  
XỬ NGOẠI LỆ (Exception Handling)  
Sau khi kết thúc chương này, bạn thể nắm được các nội dung sau:  
Định nghĩa một ngoại lệ (Exception)  
Hiểu được mục đích của việc xử ngoại lệ  
Hiểu được các kiểu ngoại lệ khác nhau trong Java  
tả mô hình xử ngoại lệ  
Hiểu được các khối lệnh chứa nhiều khối xử ngoại lệ (catch)  
tả cách sử dụng các khối ‘try’, ‘catch’ và ‘finally’  
Giải thích cách sử dụng các từ khoá ‘throw’ và ‘throws’  
Tự tạo ra các ngoại lệ  
7.1 Giới thiệu  
Exception là một loại 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 thi hành 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 đang xây dựng chương trình. Nếu bạn không xử lý các trạng thái này  
thì chương trình có thể bị kết thúc đột ngột. dụ, việc chia cho 0 sẽ tạo một  
lỗi trong chương trình. Ngôn ngữ Java cung cấp cơ chế dùng để xử ngoại lệ  
rất hiệu quả. Việc xử lý này làm hạn chế tối đa trường hợp hệ thống bị hỏng  
(crash) hay hệ thống bị ngắt đột ngột. Tính năng này làm cho Java trở thành  
một ngôn ngữ lập trình mạnh.  
7.2 Mục đích của việc xử ngoại lệ  
Một chương trình nên có cơ chế xử ngoại lệ thích hợp. Nếu không, chương  
trình sẽ bị ngắt khi một ngoại lệ xảy ra. Trong trường hợp đó, tất cả các  
nguồn tài nguyên mà hệ thống đã cấp không được giải phóng. Đ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  
hệ thống cấp nên được thu hồi lại. Tiến trình này đòi hỏi cơ chế xử lý  
ngoại lệ thích hợp.  
dụ, xét thao tác vào ra (I/O) 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 ngoại lệ sẽ xảy ra và chương trình bị hủy  
mà không đóng tập tin lại. Lúc đó tập tin dễ 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 trả lại cho hệ thống.  
7.3 Xử ngoại lệ  
Khi một ngoại lệ xảy ra, đối tượng (object) 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 nơi 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ề được xử lý. Các môi trường runtime như  
Chương 7: Xử ngoại lệ (Exception Handling)  
175  
‘IllegalAccessException’, ‘EmptyStackException’ v.v… có thể tạo ra ngoại lệ.  
Chương trình đôi khi có thể tự tạo ra ngoại lệ. Lớp ‘Throwable’ được Java  
cung cấp lớp trên cùng của lớp Exception (lớp đầu tiên trong cây thừa kế),  
lớp này là lớp cha của tất cả các ngoại lệ khác.  
7.4 Mô hình xử ngoại lệ  
Trong Java, mô hình xử ngoại lệ giám sát việc thực thi mã để phát hiện  
ngoại lệ. Mô hình xử ngoại lệ của Java được gọi là ‘catch and throw’. Trong  
mô hình này, khi một ngoại lệ xảy ra, ngoại lệ sẽ bị chặn chương trình  
chuyển đến một khối xử ngoại lệ. Người lập trình phải xử lý các ngoại lệ  
khác nhau có thể phát sinh trong chương trình. Các ngoại lệ phải được xử lý,  
hoặc thoát khỏi chương trình khi nó xảy ra.  
Ngôn ngữ Java cung cấp 5 từ khoá sau để xử lý các ngoại lệ:  
try  
catch  
throw  
throws  
finally  
Dưới đây cấu trúc của mô hình xử ngoại lệ:  
try  
{
// đoạn mã có khả năng gây ra ngoại lệ  
}
catch(Exception e1)  
{
// Nếu các lệnh trong khối ‘try’ tạo ra ngoại lệ loại e1, thì thực hiện  
//xử ngoại lệ nếu không chuyển xuống khối 'catch' tiếp theo  
}
catch(Exception e2)  
{
// Nếu các lệnh trong khối ‘try’ tạo ra ngoại lệ loại e2, thì thực hiện  
//xử ngoại lệ nếu không chuyển xuống khối 'catch' tiếp theo  
}
catch(Exception eN)  
{
// Nếu các lệnh trong khối ‘try’ tạo ra ngoại lệ loại eN, thì thực hiện  
//xử ngoại lệ nếu không chuyển xuống khối 'catch' tiếp theo  
}
finally  
{
// khối lệnh nay luôn được thực hiện cho dù ngoại lệ xảy ra hay không.  
176  
Core Java  
}
7.4.1 Các ưu điểm của mô hình ‘catch và throw’  
Mô hình ‘catch và throw’ có hai ưu điểm:  
Người lập trình chỉ phải xử ngoại lệ khi cần thiết. Không cần phải thực  
hiện tại mọi mức.  
Thông báo lỗi thể được hiện ra khi tiến hành xử ngoại lệ.  
7.4.2 Các khối ‘try’ và ‘catch’  
Khối ‘try-catch’ được sử dụng để thi hành mô hình ‘catch và throw’ của việc  
xử ngoại lệ. Khối ‘try’ chứa một tập lệnh thể thi hành được. Các ngoại lệ  
thể bị chặn khi thi hành tập lệnh này. Phương thức khả năng tạo ra  
ngoại lệ thể được khai báo trong khối ‘try’. Một hay nhiều khối ‘catch’ có  
thể theo sau một khối ‘try’. Các khối ‘catch’ này bắt các ngoại lệ khả năng  
tạo ra trong trong khối ‘try’. Hãy xem khối ‘try’ dưới đây:  
try  
{
doFileProcessing(); // phương thức do người sử dụng định nghĩa  
displayResults();  
}
catch (Exeption e) // thể hiện của ngoại lệ  
{
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 để tả các ngoại lệ xảy ra. Hình sau chỉ ra  
kết xuất của phương thức ‘printStackTrace()’.  
Hình 7.1 Khối Try và Catch  
Để xử được ngoại lệ nào, ta phải chỉ ra kiểu ngoại lệ tương ứng.  
Chương 7: Xử ngoại lệ (Exception Handling)  
177  
catch(Exception e)  
Khi ngoại lệ 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. Chương trình sẽ chuyển đến thực hiện khối ‘catch’. Để nhiều  
lớp xử lỗi hơn, như là ‘LookupException’ thay vì một đối tượng ngoại lệ  
chung (Exception e), lỗi thực tế thể một đối tượng thuộc lớp  
'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 gặp ‘catch’ của nó, nếu không tìm thấy  
chương trình phải dừng thực hiện và thoát.  
7.5 Các khối chứa nhiều Catch  
Nhiều khối ‘catch’ xử lý các loại ngoại lệ khác nhau một cách độc lập. Chúng  
được liệt kê trong đoạn mã sau:  
try  
{
doFileProcessing();  
displayResults(); }  
catch(LookupException e)  
{
// e – LookupException object  
handleLookupException(e); // phương thức xử lỗi do người sử dụng  
//định nghĩa  
}
catch(Exception e)  
{
System.err.println(“Error:” + e.printStackTrace());  
}
}
Trong trường hợp này, khối ‘catch’ đầu tiên sẽ bắt giữ một ‘LockupException’.  
Khối ‘catch’ thứ hai sẽ xử kiểu ngoại lệ khác với khối ‘catch’ thứ nhất.  
Một chương trình cũng thể chứa các khối ‘try’ lồng nhau. Ví dụ đoạn mã  
dưới đây:  
try  
{
statement 1;  
statement 2;  
try  
{
178  
Core Java  
statement1;  
statement2;  
}
catch(Exception e) // của khối try trong  
{
}
}
catch(Exception e) // của khối try ngoài  
{
}
Khi sử dụng các ‘try’ lồng nhau, khối ‘try’ bên trong được thi hành đầu tiên.  
Bất kỳ ngoại lệ nào bị chặn trong khối ‘try’ sẽ bị bắt giữ trong các khối ‘catch’  
theo sau. Nếu khối ‘catch’ thích hợp không được tìm thấy thì các khối ‘catch’  
của các khối ‘try’ bên ngoài sẽ được xem xét. Nếu không, Java Runtime  
Environment xử lý các ngoại lệ.  
chương trình 7.1 minh họa cách sử dụng các khối ‘try’ và ‘catch’.  
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 của chương trình:  
Chương 7: Xử ngoại lệ (Exception Handling)  
179  
Hình 7.2 ArithmeticException  
Trong chương trình này, một số được chia cho 0. Đây không là phép toán số  
học hợp lệ. Do đó một ngoại lệ xảy ra và được bắt giữ trong khối catch. Khi  
nhận biết được loại ngoại lệ nào có thể xảy ra, ta viết lệnh trong khối ‘catch’  
tương ứng. Ở đây, ‘a’ được sử dụng như một đối tượng của  
ArithmeticException để in các chi tiết về ngoại lệ. Nếu bạn thay thế lệnh  
‘System.out.println’ của khối ‘catch’ bằng lệnh  
System.out.println(a.getMessage())’  
thì kết xuất của chương trình như sau:  
Hình 7.3 Câu thông báo lỗi  
Khi các khối ‘try’ được sử dụng mà không có các khối ‘catch’ nào, chương  
trình sẽ biên dịch mà không gặp lỗi nào nào nhưng sẽ bị ngắt khi thực thi.  
Bởi ngoại lệ đã xảy ra khi thực thi chương trình mà không được xử lý.  
7.6 Khối ‘finally’  
Khi một ngoại lệ xuất hiện, phương thức đang được thực thi có thể bị dừng  
mà không được hoàn thành. Nếu điều này xảy ra, thì các đoạn mã phía sau  
(ví dụ như đoạn mã có chức năng thu hồi tài nguyên, như các lệnh đóng tập  
viết ở cuối phương thức) sẽ không bao giờ được gọi. Java cung cấp khối  
‘finally’ để giải quyết việc này. Khối ‘finally’ thực hiện tất cả các việc thu dọn  
khi một ngoại lệ xảy ra. Khối này có thể được sử dụng kết hợp với khối ‘try’.  
Khối ‘finally’ chứa các câu lệnh thu hồi tài nguyên về cho hệ thống hay lệnh  
in ra các câu thông báo. Các lệnh này bao gồm:  
Đóng tập tin.  
Đóng ResultSet (được sử dụng trong chương trình cơ sở dữ liệu).  
180  
Core Java  
Đóng lại các kết nối được tạo trong cơ sở dữ liệu.  
try  
{
doSomethingThatMightThrowAnException();  
}
finally  
{
cleanup();  
}
Phương thức ‘cleanup()’ được gọi nếu phương thức  
‘doSomethingThatMightThrowAnException()’ gây ra ngoại lệ. Mặt khác  
‘cleanup()’ cũng được gọi ngay khi không có ngoại lệ nào xảy ra và thực hiện  
tiếp phần sau khối lệnh ‘finally’.  
Khối ‘finally’ là tuỳ ý, không bắt buộc. Khối này được đặt sau khối ‘catch’ cuối  
cùng. Chương trình sẽ thực thi câu lệnh đầu tiên của khối ‘finally’ ngay sau  
khi gặp câu lệnh ‘return’ hay lệnh ‘break’ trong khối ‘try’.  
Khối ‘finally’ bảo đảm lúc nào cũng được thực thi, bất chấp ngoại lệ xảy ra  
hay không.  
Hình 7.4 Minh họa sự thực hiện của các khối ‘try’, ‘catch’ và ‘finally’.  
try block  
No Exception  
Exception occurs  
finally block  
catch block  
finally block  
Hình 7.4 Khối lệnh ‘try’, ‘catch’ và ‘finally’  
Chương trình 7.2 sử dụng khối ‘finally’. Ở đây, khối ‘finally’ được thi hành bất  
chấp ‘ArithmeticException’ có xảy ra hay không. Khối này khai báo các hoạt  
động thu dọn.  
Chương trình 7.2  
class FinallyDemo  
{
String name;  
int no1,no2;  
Chương 7: Xử ngoại lệ (Exception Handling)  
181  
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)  
{
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 của chương trình:  
Hình 7.5 Khối Finally  
Trong ví dụ này, các câu lệnh trong khối ‘finally’ luôn luôn thi hành, bất chấp  
ngoại lệ xảy ra hay không. Trong kết xuất trên, khối ‘finally’ được thi hành  
mặc dù không có ngoại lệ xảy ra.  
7.7 Các ngoại lệ được định nghĩa với lệnh ‘throw’ và  
‘throws’  
182  
Core Java  
Các ngoại lệ thể được tạo ra bằng cách sử dụng từ khoá ‘throw’. Từ khóa  
‘throw’ chỉ ra một ngoại lệ vừa xảy ra. Toán hạng của throw là một đối tượng  
thuộc lớp được thừa kế từ ‘Throwable’.  
Đoạn lệnh sau chỉ ra cách sử dụng của lệnh ‘throw’:  
try  
{
if (flag<0)  
{
throw new MyException(); // user-defined  
}
}
Một phương thức thể tạo ra nhiều ngoại lệ. Để làm được điều này này, ta  
chỉ cần liệt kê danh sách các ngoại lệ phương thức thể tạo ra trong  
phần định nghĩ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()’ tạo ra một ngoại lệ nhưng không được xử lý. Trong  
trường hợp này, phương thức gọi ‘x()’ nên khai báo rằng nó có khả năng tạo  
ra ngoại lệ như ngoại lệ của 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 gọi phương thức này (phương thức gọi x()).  
Đoạn mã sau minh họa cách sử dụng của từ khoá ‘throws’ để tạo nhiều ngoại  
lệ:  
public class Example  
{
// Các ngoại lệ cách nhau bởi dấu phẩy  
public void exceptionExample() throws ExException, LookupException  
{
try  
{
// các lệnh  
}
catch(ExException exmp)  
{
}
catch(LookupException lkpex)  
{
}
}
}
Trong ví dụ trên, phương thức ‘exceptionExample’ có từ khoá ‘throws’. Từ  
khoá này được theo sau bởi danh sách các ngoại lệ phương thức này có  
thể tạo ra – Trong trường hợp này là ‘ExException’ và ‘LookupException’.  
Hàm xử ngoại lệ cho các phương thức này nên khai báo các khối ‘catch’ để  
Chương 7: Xử ngoại lệ (Exception Handling)  
183  
thể xử tất cả các ngoại lệ mà các phương thể gây ra.  
Lớp ‘Exception’ thực thi giao diện ‘Throwable’ và cung cấp các tính năng để  
làm việc với ngoại lệ. Nó có ý nghĩa trong trường hợp 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 việc thừa kế lớp Exception là loại ngoại lệ mới này  
thể được 'catch' độc lập với các loại Throwable khác.  
Chương trình 7.3 minh họa ngoại lệ được định nghĩa bởi người dùng  
‘ArraySizeException’:  
Chương trình 7.3  
class ArraySizeException extends NegativeArraySizeException  
{
ArraySizeException() // constructor  
{
super(“You have passed an illegal array size”);  
}
}
class ThrowDemo  
{
int size, array[];  
ThrowDemo(int s)  
{
size=s;  
try  
{
checkSize();  
}
catch(ArraySizeException e)  
{
System.out.println(e);  
}
}
void checkSize() throws ArraySizeException  
{
if (size < 0)  
throw new ArraySizeException();  
else  
System.out.println(“The array size is ok.”);  
array = new int[3];  
for (int i=0; i<3; i++)  
array[i] = i+1;  
}
public static void main(String arg[])  
{
new ThrowDemo(Integer.parseInt(arg[0]));  
184  
Core Java  
}
}
Lớp được định nghĩa bởi người dùng ‘ArraySizeException’ là lớp con của lớp  
‘NegativeArraySizeException’. Khi một đối tượng được tạo từ lớp này, thông  
báo về ngoại lệ được in ra. Phương thức ‘checkSize()’ được gọi để tạo ra  
ngoại lệ ‘ArraySizeException’ mà được chỉ ra bởi lệnh ‘throws’. Kích thước của  
mảng được kiểm tra trong cấu trúc ‘if’. Nếu kích thước số âm thì đối tượng  
của lớp ‘ArraySizeException’ được tạo.  
Kết xuất của chương trình được chỉ ra hình 7.6.  
Hình 7.6 Ngoại lệ tự định nghĩa  
7.8 Danh sách các ngoại lệ  
Bảng sau đây liệt một số ngoại lệ:  
Ngoại lệ  
Lớp cha của thứ tự phân cấp ngoại  
lệ  
RuntimeException  
ArthmeticException  
IllegalAccessException  
IllegalArgumentException  
Lớp cơ sở cho nhiều ngoại lệ java.lang  
Lỗi về số học, dụ như ‘chia cho 0’.  
Lớp không thể truy cập.  
Đối số không hợp lệ.  
ArrayIndexOutOfBoundsExeption Lỗi tràn mảng.  
NullPointerException  
SecurityException  
Khi truy cập đối tượng null.  
Cơ chế bảo mật không cho phép thực  
hiện.  
ClassNotFoundException  
NumberFormatException  
Không thể nạp lớp yêu cầu.  
Việc chuyển đối từ chuỗi sang số thực  
không thành công.  
AWTException  
Ngoại lệ về AWT  
IOException  
FileNotFoundException  
EOFException  
Lớp cha của các lớp ngoại lệ I/O  
Không thể định vị tập tin  
Kết thúc một tập tin.  
NoSuchMethodException  
InterruptedException  
Phương thức yêu cầu không tồn tại.  
Khi một luồng bị ngắt.  
Bảng 7.1 Danh sách một số ngoại lệ  
Chương 7: Xử ngoại lệ (Exception Handling)  
185  
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 được xử lý, nếu không ứng dụng sẽ bị ngắt.  
Việc xử ngoại lệ cho phép bạn kết hợp tất cả tiến trình xử lỗi trong  
một nơi. Lúc đó đoạn 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’ gây ra ngoại lệ còn khối ‘catch’ xử ngoại lệ.  
Nhiều khối catch có thể được sử dụng để xử lý các loại ngoại lệ khác  
nhau.  
Từ khoá ‘throws’ liệt kê các ngoại lệ phương gây ra.  
Từ khoá ‘throw’ tạo ra một ngoại lệ.  
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 thông báo.  
186  
Core Java  
Kiểm tra sự tiến bộ  
1. Khi một ngoại lệ xảy ra, môt .........................đại diện cho ngoại lệ  
được tạo ra.  
2. Lớp .......................là lớp cha của lớp Exception  
3. Mô hình xử lỗi của Java được gọi là mô hình 'catch and throw'?  
Đúng/Sai  
4. Ưu điểm của mô hình 'catch and throw' là gì?  
5. Khi sử dụng 'try' lồng nhau, 'try' ngoài sẽ được thực hiện trước?  
Đúng/Sai  
6. Khối 'finally' đảm bảo luôn luôn được thực hiện cho dù có ngoại lệ xảy  
ra hay không?  
Đúng/Sai  
7. Mỗi phương thức không có khả năng gây ra nhiều hơn một ngoại lệ.  
Đúng/Sai  
8. Ngoại lệ .................................... được tạo ra khi lớp không thể truy  
cập được.  
Chương 7: Xử ngoại lệ (Exception Handling)  
187  
Bài tập  
1. Viết chương trình gây ra ngoại lệ khi người sử dụng không nhập tham  
số nào vào từ dòng lệnh. Chương trình phải hiện thị số tham số nếu  
có tham số được nhập vào từ dòng lệnh. Đầu ra của chương trình như  
sau:  
2. Viết chương trình gây ra ngoại lệ, nếu không có số nào được nhập vào  
từ dòng lệnh. Ngược lại, chương trình hiển thị giá trị lập phương của  
số nhập vào như hình dưới đây:  
3. Viết chương trình gây ra ngoại lệ nếu như lớp không thể truy nhập.  
188  
Core Java  
doc 14 trang Thùy Anh 27/04/2022 9640
Bạn đang xem tài liệu "Giáo trình Core Java - Chương 7: Xử lý ngoại lệ", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

File đính kèm:

  • docgiao_trinh_core_java_chuong_7_xu_ly_ngoai_le.doc