1. Java 異常處理:
異常是程序中的一些錯誤,但并不是所有的錯誤都是異常,并且錯誤有時候是可以避免的。
- 比如說,你的代碼少了一個分號,那么運行出來結果是提示是錯 java.lang.Error;
- 如果你用System.out.println(11/0),那么你是因為你用0做了除數,會拋出 java.lang.ArithmeticException 的異常。
1.1 異常分析
異常發生的原因有很多,通常包含以下幾大類:
- 用戶輸入了非法數據。
- 要打開的文件不存在。
- 網絡通信時連接中斷,或者JVM內存溢出。
這些異常有的是因為用戶錯誤引起,有的是程序錯誤引起的,還有其它一些是因為物理錯誤引起的。
一要理解Java異常處理是如何工作的,你需要掌握以下三種類型的異常:
檢查性異常:
- 最具代表的檢查性異常是用戶錯誤或問題引起的異常,這是程序員無法預見的。
- 例如要打開一個不存在文件時,一個異常就發生了,這些異常在編譯時不能被簡單地忽略。
運行時異常:
- 運行時異常是可能被程序員避免的異常。
- 與檢查性異常相反,運行時異常可以在編譯時被忽略。
錯誤:
- 錯誤不是異常,而是脫離程序員控制的問題。
- 錯誤在代碼中通常被忽略。
- 例如,當棧溢出時,一個錯誤就發生了,它們在編譯也檢查不到的。
1.2 Exception 類的層次
-
所有的異常類是從 java.lang.Exception 類繼承的子類。
-
Exception 類是 Throwable 類的子類。除了Exception類外,Throwable還有一個子類Error 。
Java 程序通常不捕獲錯誤。錯誤一般發生在嚴重故障時,它們在Java程序處理的范疇之外。
-
Error 用來指示運行時環境發生的錯誤。
例如,JVM 內存溢出。一般地,程序不會從錯誤中恢復。 -
異常類有兩個主要的子類:IOException 類和 RuntimeException 類。
在 Java 內置類中,有大部分常用檢查性和非檢查性異常。
捕獲異常:
- 使用 try 和 catch 關鍵字可以捕獲異常。
- try/catch 代碼塊放在異常可能發生的地方。
- try/catch代碼塊中的代碼稱為保護代碼。
使用 try/catch 的語法如下:
try
{// 程序代碼
}catch(ExceptionName e1)
{//Catch 塊
}
- Catch 語句包含要捕獲異常類型的聲明。
- 當保護代碼塊中發生一個異常時,try 后面的 catch 塊就會被檢查。
- 如果發生的異常包含在 catch 塊中,異常會被傳遞到該 catch 塊,這和傳遞一個參數到方法是一樣。
下面的例子中聲明有兩個元素的一個數組,當代碼試圖訪問數組的第三個元素的時候就會拋出一個異常。
import java.io.*;
public class ExcepTest{public static void main(String args[]){try{int a[] = new int[2];System.out.println("Access element three :" + a[3]);}catch(ArrayIndexOutOfBoundsException e){System.out.println("Exception thrown :" + e);}System.out.println("Out of the block");}
}
以上代碼編譯運行輸出結果如下:
Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3
Out of the block
1.3 多重捕獲塊:
一個 try 代碼塊后面跟隨多個 catch 代碼塊的情況就叫多重捕獲。
- 多重捕獲塊的語法如下所示:
try{ // 程序代碼 }
catch(異常類型1 異常的變量名1){ // 程序代碼 }
catch(異常類型2 異常的變量名2){ // 程序代碼 }
catch(異常類型2 異常的變量名2){ // 程序代碼 }
上面的代碼段包含了 3 個 catch塊。
可以在 try 語句后面添加任意數量的 catch 塊。
如果保護代碼中發生異常,異常被拋給第一個 catch 塊。
- 如果拋出異常的數據類型與 ExceptionType1 匹配,它在這里就會被捕獲。
- 如果不匹配,它會被傳遞給第二個 catch 塊。
- 直到異常被捕獲或者通過所有的 catch 塊。
1.4 throws/throw 關鍵字:
如果一個方法沒有捕獲到一個檢查性異常,那么該方法必須使用 throws 關鍵字來聲明。throws 關鍵字放在方法簽名的尾部。
- 也可以使用 throw 關鍵字拋出一個異常,無論它是新實例化的還是剛捕獲到的。
下面方法的聲明拋出一個 RemoteException 異常:
import java.io.*;
public class className
{public void deposit(double amount) throws RemoteException{// Method implementationthrow new RemoteException();}//Remainder of class definition
}
!一個方法可以聲明拋出多個異常,多個異常之間用逗號隔開。
例如,下面的方法聲明拋出 RemoteException 和 InsufficientFundsException:
import java.io.*;
public class className
{public void withdraw(double amount) throws RemoteException,InsufficientFundsException{// Method implementation}//Remainder of class definition
}
1.5 finally關鍵字:
- finally 關鍵字用來創建在 try 代碼塊后面執行的代碼塊。
- 無論是否發生異常,finally 代碼塊中的代碼總會被執行。=
- 在 finally 代碼塊中,可以運行清理類型等收尾善后性質的語句。
finally 代碼塊出現在 catch 代碼塊最后,語法如下:
try{ // 程序代碼 }
catch(異常類型1 異常的變量名1){ // 程序代碼 }
catch(異常類型2 異常的變量名2){ // 程序代碼 }
finally{ // 程序代碼 }
注意下面事項:
-
catch 不能獨立于 try 存在。
-
在 try/catch 后面添加 finally 塊并非強制性要求的。
-
try 代碼后不能既沒 catch 塊也沒 finally 塊。
-
try, catch, finally 塊之間不能添加任何代碼。
1.6 聲明自定義異常:
在 Java 中你可以自定義異常。編寫自己的異常類時需要記住下面的幾點。
-
所有異常都必須是 Throwable 的子類。
-
如果希望寫一個檢查性異常類,則需要繼承 Exception 類。
-
如果你想寫一個運行時異常類,那么需要繼承 RuntimeException 類。
可以像下面這樣定義自己的異常類:
class MyException extends Exception{ }
- 只繼承Exception 類來創建的異常類是檢查性異常類。
下面的 InsufficientFundsException 類是用戶定義的異常類,它繼承自 Exception。
一個異常類和其它任何類一樣,包含有變量和方法。
以下實例是一個銀行賬戶的模擬,通過銀行卡的號碼完成識別,可以進行存錢和取錢的操作。
import java.io.*;
//自定義異常類,繼承Exception類
public class InsufficientFundsException extends Exception
{//此處的amount用來儲存當出現異常(取出錢多于余額時)所缺乏的錢private double amount;public InsufficientFundsException(double amount){this.amount = amount;}public double getAmount(){return amount;}
}
為了展示如何使用我們自定義的異常類,
在下面的 CheckingAccount 類中包含一個 withdraw() 方法拋出一個 InsufficientFundsException 異常。
import java.io.*;
//此類模擬銀行賬戶
public class CheckingAccount
{//balance為余額,number為卡號private double balance;private int number;public CheckingAccount(int number){this.number = number;}//方法:存錢public void deposit(double amount){balance += amount;}//方法:取錢public void withdraw(double amount) throws InsufficientFundsException{if(amount <= balance){balance -= amount;}else{double needs = amount - balance;throw new InsufficientFundsException(needs);}}//方法:返回余額public double getBalance(){return balance;}//方法:返回卡號public int getNumber(){return number;}
}
下面的 BankDemo 程序示范了如何調用 CheckingAccount 類的 deposit() 和 withdraw() 方法。
public class BankDemo
{public static void main(String [] args){CheckingAccount c = new CheckingAccount(101);System.out.println("Depositing $500...");c.deposit(500.00);try{System.out.println("\nWithdrawing $100...");c.withdraw(100.00);System.out.println("\nWithdrawing $600...");c.withdraw(600.00);}catch(InsufficientFundsException e){System.out.println("Sorry, but you are short $" + e.getAmount());e.printStackTrace();}}
}
編譯上面三個文件,并運行程序 BankDemo,得到結果如下所示:
Depositing $500...
Withdrawing $100...
Withdrawing $600...
Sorry, but you are short $200.0
InsufficientFundsExceptionat CheckingAccount.withdraw(CheckingAccount.java:25)at BankDemo.main(BankDemo.java:13)
1.7 通用異常:
在Java中定義了兩種類型的異常和錯誤。
-
JVM(Java虛擬機) 異常:
- 由 JVM 拋出的異常或錯誤。
- 例如:NullPointerException 類,ArrayIndexOutOfBoundsException 類,ClassCastException 類。
-
程序級異常:
- 由程序或者API程序拋出的異常。
- 例如 IllegalArgumentException 類,IllegalStateException 類。
2. ??Java基礎專欄 - 前篇回顧
- 認識Java,Java程序的生命周期,運行Java程序
- Java數據類型闡述、基本數據類型的占用和范圍、二進制的講述
- 8種基本數據類型的分析、數據類型轉換規則、轉義字符的列舉
- 五種運算符的說明(&&、||、>=、>、<=、<)、4種控制語句(if、for、while、dowhile)、輸入和輸出說明
- 方法的概念、方法的調用、方法重載、構造方法的創建
- 全方面帶你了解Java里的日期與時間內容,介紹 Calendar、GregorianCalendar、Date類
- 正則表達式的使用與常用類分享
- Stream流、文件File相關操作,IO的含義與運用
3. 💕👉 其他好文推薦
- 還不了解Git分布式版本控制器?本文將帶你全面了解并掌握
- 帶你認識Maven的依賴、繼承和聚合都是什么!有什么用?
- 2-3樹思想與紅黑樹的實現與基本原理
- !全網最全! ElasticSearch8.7 搭配 SpringDataElasticSearch5.1 的使用
- 全面深入Java GC!!帶你完全了解 GC垃圾回收機制!!
- 全面了解Java的內存模型(JMM)!詳細清晰!
- 在JVM中,類是如何被加載的呢?本篇文章就帶你認識類加載的一套流程!
- 帶你了解Go語言的判斷語句、切片和映射表!!
- (Java并發編程—JUC)帶你重新認識進程與線程!!讓你深層次了解線程運行的睡眠與打斷!!