### java異常處理語法結構 ###
try
{
// 業務實現代碼
}
catch
{
// 異常處理塊1
}
catch
{
// 異常處理塊2
}
finally
{
// 資源回收快
}
### 異常概述 ###
異常機制可以使程序中的異常處理代碼和正常業務代碼分離。
先處理小異常,再處理大異常。
異常能處理就早處理,拋出不去還不能處理的就想法消化掉或者轉換爲RuntimeException處理。
可以把錯誤集中起來,一次處理所有的錯誤。
五個關鍵字try,catch,finally,throw,throws
其中try...catch用來捕捉異常。
拋出大量異常是有問題的,應該從程序開發角度儘可能的控制異常發生的可能。
不要使用過於龐大的try塊,造成後面緊跟大量的catch,導致分析異常原因的難度大大增加。
儘量避免在實際應用中捕捉Throwable。
不要忽略捕捉到的異常,catch爲空或僅僅打印出錯信息都是不妥的,要處理異常或重新拋出異常。
### 作用以及限制 ###
作用:
①what
如果異常機制使用恰當,被拋出異常的類型可以表明發生了什麼程序錯誤。
②where
發生異常之後,而Stack Trace可以清楚的告訴我們什麼地方發生了錯誤。
③why
爲什麼發生錯誤則可以通過看異常信息和Stack Trace來分析。
如果你的異常不能解決上面的3W問題,那麼可以證明你對異常使用一定不正確。
限制:
1 把異常和普通錯誤混在一起。
2 使用異常處理代替流程控制。
其實,對於普通的錯誤,應該編寫處理這種錯誤的代碼,增加程序的健壯性,只用對外部的、不能確定和預知的運行時錯誤才使用異常。不要使用一場來代替正常的業務邏輯判斷。
### try塊裏聲明的變量只能在try塊裏有效,在catch塊裏不可以使用
### 分類 ###
1 Error與Exception
Error:稱爲錯誤,由Java虛擬機生成並拋出,包括動態鏈接失敗、虛擬機錯誤等,程序對其不做處理,也可以說成不可以處理的異常。
Exception:所有異常類的父類,其子類對應了各種各種具體可能出現的異常事件,一般需要用戶聲明或捕獲,也叫可處理的異常。
2 runtimeException與非運行時異常(其他異常)
runtimeException:一類特殊的異常,如被0除、數組下界超範圍,其產生比較頻繁,處理麻煩,如果聲明或捕獲將會對程序可讀性和運行效率影響很大。因此係統自動檢測並將它們交給缺省的異常處理程序,這樣的異常可以處理也可以不處理。
非運行時異常:是RuntimeException以外的異常,類型上都屬於Exception類及其子類,這類異常是必須要處理的異常,否則程序就不能編譯通過。
### 可同時捕獲多個異常 ###
捕獲多異常,異常類型用 | 分開;
捕獲多異常時,異常變量有隱形的final修飾,因此程序不能對異常變量重新賦值。
### 訪問異常信息的方法 ###
printStackTrace():將跟蹤棧信息輸出到標準錯誤輸出。
雖然printStackTrace可以很方便的追蹤異常的發生情況,可以用來調試程序,但在最後發佈的程序中,應該避免使用它,而應該對捕獲的一場進行適當的處理。
getStackTrace():返回該異常的跟蹤棧信息。
### finally ###
回收try塊中打開的一些物理資源(數據庫連接,網絡連接,和磁盤連接等)。
java的垃圾回收機制不會回收任何物理資源,只能回收堆內存中對象所佔用的內存。
除非在try塊或catch塊裏調用了退出JVM的System.exit(),否則異常處理的finally塊總會執行。
通常情況下不要再finally塊中使用return或throw語句,否則會導致try、catch裏的throw、return語句失效。
### 自動關閉資源的try語句 ###
### throws ###
如果某段代碼調用了一個帶有throws聲明的方法,拋出checked異常,則表明該方法希望他的調用者來處理該異常。
否則將異常交給JVM處理,打印異常的跟蹤棧信息,並終止程序運行。
子類拋出的異常不允許比父類多。
### throw 及自定義異常類###
自行拋出異常時,拋出RuntimeException更好,更靈活
throw new Exception
程序:
```
public class ThrowTest
{
public static void main(String[] args)
{
try
{
// 調用聲明拋出Checked異常的方法,要麼顯式捕獲該異常
// 要麼在main方法中再次聲明拋出
throwChecked(-3);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
// 調用聲明拋出Runtime異常的方法既可以顯式捕獲該異常,
// 也可不理會該異常
throwRuntime(3);
}
public static void throwChecked(int a)throws Exception
{
if (a > 0)
{
//自行拋出Exception異常
//該代碼必須處於try塊裏,或處於帶throws聲明的方法中
throw new Exception("a的值大於0,不符合要求");
}
}
public static void throwRuntime(int a)
{
if (a > 0)
{
//自行拋出RuntimeException異常,既可以顯式捕獲該異常
//也可完全不理會該異常,把該異常交給該方法調用者處理
throw new RuntimeException("a的值大於0,不符合要求");
}
}
}
很少拋出自定義異常類
### catch和throw同時使用 ###
public class AuctionTest
{
private double initPrice = 30.0;
// 因爲該方法中顯式拋出了AuctionException異常,
// 所以此處需要聲明拋出AuctionException異常
public void bid(String bidPrice)
throws AuctionException
{
double d = 0.0;
try
{
d = Double.parseDouble(bidPrice);
}
catch (Exception e)
{
// 此處完成本方法中可以對異常執行的修復處理,
// 此處僅僅是在控制檯打印異常跟蹤棧信息。
e.printStackTrace();
//再次拋出自定義異常
throw new AuctionException("競拍價必須是數值,"
+ "不能包含其他字符!");
}
if (initPrice > d)
{
throw new AuctionException("競拍價比起拍價低,"
+ "不允許競拍!");
}
initPrice = d;
}
public static void main(String[] args)
{
AuctionTest at = new AuctionTest();
try
{
at.bid("df");
}
catch (AuctionException ae)
{
// 再次捕捉到bid方法中的異常。並對該異常進行處理
System.err.println(ae.getMessage());
}
}
}
“`
catch和throw結合使用的情況在大型企業級應用中使用的非常頻繁,使用方法:
1 通過日誌記錄異常發生時的情況
2 應用需要根據應用使用者傳達某種提示