全部章節 >>>>
本章目錄
5.1 異常概述
生活中的異常
程序中的異常
5.1.1 程序中的異常
在Java語言中,異常是指程序在運行期間發生的事件,它是導致程序中斷運行的正常指令流。
例如,在算術運算中除數爲0、數組越界、空指針異常等,這些事件的發生都會阻止程序的正常運行。
示例:演示除法運算
public class MathCalc {
public static int division(int dividend,int divisor){
return dividend/divisor;
}
public static void main(String[] args) {
System.out.println(MathCalc.division(100, 0));
}
}
5.1.2 異常分類
1、Throwable類
位於異常類層次結構的頂端,它是Java中所有錯誤和異常的父類。
2、Error類
通常指與虛擬機相關的問題,如系統崩潰、虛擬機錯誤、動態鏈接失敗等。
這種錯誤無法恢復或不可能捕獲,將導致應用程序中斷。通常程序無法處理這些錯誤。
3、Exeception類
該類型的異常在程序中發生後可以進行捕獲處理,處理後程序正常運行,從而保證程序的穩定性及健壯性。
Java程序開發中的異常處理,主要是針對Exception類及其子類進行的。
示例:演示數組下標越界異常
public class RunException {
public static void showRuntimeException(){
int[] data=new int[2];
System.out.println(data[2]);
}
public static void main(String[] args) {
RunException.showRuntimeException();
}
}
分析:
- 上述程序的數組長度爲2,數組中元素的索引範圍爲0~1,當程序取索引值1時,超出了索引的取值範圍,從而產生了數組下標越界。
- 由於沒有進行異常處理,程序立即終止。
- 該異常屬於運行時異常,其特點是:程序編譯時可通過,但運行時卻發生異常。
常見運行時異常RuntimeException
異常類名稱 |
說明 |
ArithmeticException |
算術異常 |
ArrayIndexOutOfBoundsException |
數組索引爲負或大於等於數組大小異常 |
ClassCastException |
對象轉換異常 |
IllegalArgumentException |
調用方法時傳入非法參賽異常 |
IndexOutOfBoundsException |
數組索引越界異常 |
NegativeArraySizeException |
數組長度爲負值異常 |
NullPointerException |
空指針指向異常 |
NumberFormatException |
數字格式異常 |
StringIndexOutOfBoundsException |
字符串索引越界異常 |
UnsupportedOperationException |
操作錯誤異常 |
5.1.3 實踐練習
5.2 try-catch處理異常
Java異常處理的作用和運行機制:
Java的異常處理機制可以保障程序具有良好的容錯性,使程序健壯性更高。
當程序運行出現意外情形時,系統會自動生成一個Exception類型的子類對象來通知程序,從而實現業務功能的代碼與錯誤處理代碼分離,使程序具有更好的可讀性。
Java的異常處理機制提供了兩種方式來處理異常,一種是使用“try-catch”語句處理異常,另一種是在方法聲明時使用throws關鍵字將異常拋出。
語法:
try{
//可能出現異常的語句
}catch(異常類型1 異常對象1){
//異常處理代碼
}
示例:演示try-catch捕獲異常
try{
//創建Scanner對象,用於接收控制檯輸入的數據
Scanner input=new Scanner(System.in);
System.out.println("請輸一個整數除數:");
int num=input.nextInt();
System.out.println("您輸入的數字是:"+num);
}catch(InputMismatchException e){
System.err.println("輸入不匹配異常:程序只能接收整數");
}
注意:
一個try塊可以對應多個catch塊,構成多重catch語句塊,多重catch語句塊用於對多個不同的 異常類型進行捕獲,但最多隻能選中一個執行。
先處理小異常,再處理大異常。即進行異常捕獲時不僅應該將Exception類對應的catch塊放在最後,而且所有父類異常的catch 塊都應該放在子類異常catch塊的後面,否則將出現編譯錯誤。
示例:演示多重catch語句塊
try{
Scanner input=new Scanner(System.in);
System.out.println("請輸入被除數:");
int divisor=input.nextInt();
System.out.println("請輸出除數:");
int dividend=input.nextInt();
System.out.println("您輸入的兩個數的是:"+divisor/dividend);
}catch(InputMismatchException e){
System.err.println("輸入不匹配異常:程序只能接收整數");
}
catch (ArithmeticException e) {
System.err.println("算數異常:0不能作爲被除數");
}catch(Exception e){
System.err.println("未知異常");
}
注意:catch塊範圍大的異常放在後面
5.2.2 使用finally回收資源
語法:
try{
//可能出現異常的語句
}catch(異常類型1 異常對象1){
//異常處理代碼
} finally{
//資源回收代碼
}
說明:
finally塊保證回收在try塊中打開的物理資源,如數據庫連接、網絡連接或磁盤文件等。
無論try語句塊中的代碼是否出現異常,try語句塊對應的任意一個catch語句塊是否被執行,甚至在try或catch語句塊中執行了return語句,finally塊總會被執行。
無論是try語句塊還是catch語句塊中使用return語句,都要先執行完finally語句塊後,再返回當前方法。
try語句不能獨立存在,其後至少要有一個catch語句塊或finally語句塊。
finally語句塊不是必須存在的,可以根據需求決定是否添加。
示例:使用try-catch-finally模擬文件操作過程中的異常處理
try{
//創建Scanner對象,用於接收控制檯輸入的數據
Scanner input=new Scanner(System.in);
System.out.println("請輸一個整數除數:");
int num=input.nextInt();
System.out.println("您輸入的數字是:"+num);
}catch(InputMismatchException e){
System.err.println("輸入不匹配異常:程序只能接收整數");
}
5.2.3 實踐練習
5.3 throws與throw
Java 強烈要求應用程序進行完整的異常處理。
throws用來聲明一個方法可能拋出的所有異常信息。通常不用顯示地捕獲異常,系統將自動將異常拋給上級方法,throws出現在方法的頭部。
throw指程序運行中拋出的一個具體的異常Exception,拋出的Exception需要用戶來捕獲處理。
語法:
[訪問控制符] 返回類型 方法名稱([參數列表]) throws 異常類1, 異常類2…
{
}
當前方法不知道如何處理當前異常時,可以使用throws關鍵字聲明拋出異常,該異常可由上一級調用者處理。
throws聲明只能在方法簽名中使用。
throws可以聲明拋出多個異常類,多個異常類之間以逗號隔開。
5.3.1 使用throws聲明拋出異常
示例:在讀取文件方法聲明時使用Throws拋出可能異常
public class Read {
//使用throws拋出程序可能發生的異常類,可由調用該方法處捕獲處理
public static void readFile() throws ClassNotFoundException,FileNotFoundException{
//將com.java.Read類加載到JVM的內存中
Class.forName("com.java.Read");
//創建FileInputStream實例,用於讀取文件中的數據
FileInputStream fis=new FileInputStream("c://file.txt");
}
public static void main(String[] args) {
try {
Read.readFile();
} catch (FileNotFoundException e) {
e.printStackTrace();//顯示堆棧異常信息
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
如果在main()方法中未使用try-catch捕獲readFile()方法拋出的異常,而是在main()中繼續將異常拋出,此時該異常交給JVM虛擬機進行處理。
不提倡開發人員在main()中將異常繼續向上拋給JVM。
5.3.2 使用throw拋出異常
語法:
throw 異常類對象
在實際的企業項目開發中,系統是否要拋出異常,可能需要根據應用的業務需求來決定,如果程序中的數據處理與指定的業務需求不符,這就是一種異常。
與業務需求不符而產生的異常,必須由開發人員來決定拋出,系統無法拋出這種異常。
如果需要在程序中自行拋出異常,則應該使用throw語句。
throw語句拋出的不是一個異常類,而是一個異常實例,且每次只能拋出一個異常實例。
示例:使用throw拋出異常保證員工年齡合乎企業用人規則
public class UserInfo {
private String name;
private int age;
...
public void setAge(int age) throws Exception {
if(age<18 || age>60){
//使用throw拋出異常
throw new Exception("員工年齡應該在18歲至60歲之間");
}
this.age = age;
}
...
public static void main(String[] args) {
UserInfo userInfo=new UserInfo();
userInfo.setName("俞敏紅"); //姓名賦值
try {
userInfo.setAge(10); //年齡賦值
userInfo.showEmpInfo(); //顯示員工信息
} catch (Exception e) {
e.printStackTrace();
}
}
}
throws和throw的區別
throws |
throw |
聲明一個方法可能拋出的所有異常類型 |
拋出一個具體的異常類實例 |
不用顯式地捕獲異常,可由系統自動將所有捕獲的異常信息拋給上級方法(即方法的調用者) |
需要程序員自行捕獲相關的異常 |
throws在方法頭聲明 |
throw在方法內部使用 |
5.3.3 實踐練習
5.4 自定義異常
問題1:將員工的工資輸入爲負數。
問題2:將訂單的下單日期輸入爲超過當期時間。
。。。
5.4.1 創建自定義異常
自定義異常類需要繼承自Exception類。
示例:創建自定義異常類
public class AuctionException extends Exception{
//無參構造方法
public AuctionException(){
}
public AuctionException(String message){
//調用父類有參構造器
super(message);
}
}
5.4.2 自定義異常應用
1、異常處理的複雜性
異常不能由當前方法處理。
異常由當前方法處理一部分,另一部分交由當前方法的調用者進行處理,此時需要在當前方法中拋出異常。
2、多個方法相互協作處理異常
示例:使用自定義異常處理拍賣過程中的錯誤操作(亦可說使用自定義異常處理拍賣過程中的業務邏輯異常)。
public class AuctionTest {
private double initPrice=30; //起拍價
public void bid(String bidPrice) throws AuctionException{
double d=0;
try {
//將字符串格式的小數轉換爲double類型的數據
d=Double.parseDouble(bidPrice);
} catch (Exception e) {
e.printStackTrace();
//拋出自定義異常
throw new AuctionException("輸入的競拍價格必須爲小數格式");
}
if(initPrice>d){
//如果競拍價格低於起拍價格,則視爲異常,使用throw拋出自定義異常對象
throw new AuctionException("競拍價格低於起拍價格,不許競拍");
}
initPrice=d;
}
public class AuctionTest {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
System.out.println("請輸入商品的競拍價格:");
AuctionTest auctionTest=new AuctionTest();
try {
auctionTest.bid(input.next());
} catch (AuctionException e) {
//捕獲bid()方法拋出的異常,顯示異常提示信息
System.out.println(e.getMessage());
}
}
}
5.4.3 實踐練習
總結:
- Java的異常處理機制可以保障程序具有良好的容錯性,使程序健壯性更高。Exception是Java異常的父類。
- 運行時異常的父類是RuntimeException,它的特點是程序編譯時可通過,但運行時卻發生異常。常見的運行時異常有:ArithmeticException、ArrayIndexOutOfBoundsException、NullPointerException、ClassCastException、IllegalArgumentException
- Java的異常處理機制提供了兩種方式來處理異常,一種是使用“try-catch”語句處理異常,它將可能發生異常的代碼放在try塊,異常處理代碼放在catch塊;另一種是在方法聲明時使用throws關鍵字將異常拋出,拋出的異常由調用者進行處理
- finally塊保證回收在try塊中打開的物理資源,如數據庫連接、網絡連接或磁盤文件等。
- 在方法中可以使用throw主動拋出一個異常對象。
- 自定義異常類需要繼承自Exception類,定義合適的自定義異常可以解決業務邏輯規則的不正常情況。