java異常處理01-異常分類
什么是Java異常?
當(dāng)Java程序的正常行為被意外行為中斷時季率,會發(fā)生故障茸塞。這種故障被稱為異常躲庄。例如,程序嘗試打開文件以讀取其內(nèi)容钾虐,但該文件不存在將產(chǎn)生異常噪窘。Java將異常分為幾種類型,所以讓我們考慮每一種類型效扫。
檢查異常
Java將(例如FileNotFoundException, IOException)引起的異常分類為已檢查的異常效览。Java編譯器會檢查這些異常,并且在異常發(fā)生的位置要求進(jìn)行捕獲處理或者向上拋出(throws)荡短。需要注意的是檢查異常屬于編譯器的行為丐枉,要求你必須在代碼中捕獲或向上拋出(throws)。
運(yùn)行時(非檢查)異常
例如程序進(jìn)行強(qiáng)制轉(zhuǎn)換(cast)掘托,這種可能存在轉(zhuǎn)換失敗的異常就是另一種異常瘦锹。即運(yùn)行時異常(RuntimeException)。和檢查不同,編譯器不會檢查你在代碼中是否進(jìn)行處理或拋出弯院。運(yùn)行時異常通常來自編寫的不良代碼辱士,因此應(yīng)由程序員修復(fù)。
錯誤(Error)
指一些非常嚴(yán)重听绳,通常無法進(jìn)行修正必須要重啟程序的異常颂碘。例如, 嘗試從JVM分配內(nèi)存椅挣,但沒有足夠的可用內(nèi)存來滿足請求(OutOfMemoryError)头岔。運(yùn)行時嘗試調(diào)用加載類文件但類文件但無法找到時(NoClassDefFoundError)。對于錯誤您永遠(yuǎn)不應(yīng)該嘗試捕獲并自己處理錯誤鼠证,因為JVM可能已經(jīng)無法從中恢復(fù)正常峡竣。
Throwable及其子類
Java提供了表示不同類型異常的類層次結(jié)構(gòu)。java.lang
包的Throwable
類是所有異常類的超類量九。
/
└────Throwable
├────Error
│ ├────NoClassDefFoundError
│ └────OutOfMemoryError
└────Exception
├────RuntimeException
│ ├────IllegalArgumentException
│ └────NullPointerException
├────FileNotFoundException
└────IOException
(注: 該圖使用https://github.com/harbby/gadtry Graph功能繪制)
注意:通常您不應(yīng)該以任何方式捕獲和處理Throwable适掰。
Exception類
Throwable有兩個直接的子類。其中一個子類是Exception荠列。Java提供了許多直接子類的異常類Exception
类浪。比如:
SQLException 表示發(fā)生了jdbc異常,來自
java.sql
包中IOException 表示發(fā)生了I/O異常肌似,來自
java.io
包中
注意费就,每個Exception
子類名稱都以Exception
單詞結(jié)尾。該約定使得易于識別該類異常锈嫩。
您可能想自定義使用自己的Exception檢查異常
受楼。下面自定義示例:
public class MyException extends Exception
{
public MyException(String message)
{
super(message);
}
public MyException(String message, Throwable cause)
{
super(message, cause);
}
public MyException(Throwable cause)
{
super(cause);
}
}
Error類
Throwable另一個直接的子類是Error
垦搬,描述了一個合理的應(yīng)用程序不應(yīng)該嘗試處理的嚴(yán)重問題 - 例如內(nèi)存不足溢出呼寸,棧溢出,或者嘗試加載無法找到的類猴贰。例如:
- OutOfMemoryError 內(nèi)存溢出
- StackOverflowError 棧溢出
- NoClassDefFoundError 嘗試加載無法找到的類時觸發(fā)
注意:通常您不應(yīng)該以任何方式捕獲和處理Error類異常对雪。
RuntimeException類
RuntimeException異常或其子類實(shí)例化是未經(jīng)檢查的異常米绕。直接父類是Exception瑟捣。RuntimeException和其分類Exception 聲明相同的構(gòu)造函數(shù)(具有相同的參數(shù)列表)。它通常表示一個可能由不良代碼引起的運(yùn)行時異常栅干。下面是它的一些示例:
- NullPointerException 空指針異常迈套,java最常見異常。過多的該異常通常意味您需要提高代碼編寫技巧碱鳞。
- IllegalArgumentException 驗證異常桑李,通常表示參數(shù)非法或不正確的狀態(tài)。
- ClassCastException 類型轉(zhuǎn)換異常
NullPointerException異常優(yōu)化:
- 嘗試使用
java.util.Optional<T>
作為方法返回值,使用Optional.empty()取代return null
贵白; - 使用將字符串放在前面
"str".equals(arg)
- 做好方法或構(gòu)造函數(shù)的入?yún)z查率拒。
this.args = Objects.requireNonNull(inArgs, "inArgs is null");
- 返回空集合而不是null。
return new String[0]
orreturn Collections.emptyMap()
- 方法入?yún)⒑头祷厥褂?
long,int
而非包裝類Intger,Long
異常拋出
C語言通常return全局錯誤變量來通常調(diào)用者禁荒。而java則使用拋出異常對象來通知調(diào)用者猬膨。了解如何以及何時拋出異常是Java編程一個非常重要技能。通常您只拋出Exception
或RuntimeException
的子類實(shí)例化的對象呛伴。拋出異常有兩個步驟。
- 使用
throw new 異常
語句拋出異常對象磷蜀。 - 在方法上使用
throws 異常
語句告知編譯器(對于檢查異常這是必須的)。
throw拋出異常:
throw new SQLException();
throw new FileNotFoundException("not find file " + fileName);
異常拋出是指將異常對象從當(dāng)前方法拋出到JVM污它。然后JVM會在異常表中查找合適異常處理邏輯(catch)。如何沒有找到則JVM會退出當(dāng)前方法的調(diào)用棧庶弃,從上級調(diào)用者(方法)的異常表中繼續(xù)尋找衫贬。如果找到它將使用該處理代碼進(jìn)行處理異常。如果JVM最后在main()方法的異常表中依然沒有找到合適處理邏輯(catch)那么JVM將會發(fā)出消息-1然后退出歇攻。
注意: 異常處理通常非常昂貴,您不該在任何時候使用異常處理邏輯來處理您的正常業(yè)務(wù)
throws告知編譯器:
從方法中拋出檢查異常時葬毫,需要在方法上添加拋出標(biāo)志來通知編譯器。
public static void main(String[] args) throws SQLException {}
總結(jié)
該篇文檔總結(jié)java異常的分類和各自的特點(diǎn)屡穗。下面是一些關(guān)鍵點(diǎn)總結(jié):
強(qiáng)制你處理或拋出
檢查異常
屬于編譯器的行為贴捡,對于它編譯器要求你必須在代碼中捕獲或向上拋出(throws)。永遠(yuǎn)不要試圖catch Error錯誤嘗試捕獲并自己處理錯誤村砂,因為JVM可能已經(jīng)無法從中恢復(fù)正常烂斋。
永遠(yuǎn)不要以任何方式直接catch捕獲和處理Throwable, 因為Error是它子類础废。
異常處理通常代價非常昂貴,不要試圖用來處理您的正常業(yè)務(wù)评腺。
過多的NullPointerException異常意味著你需要提高代碼編寫技巧。