開心一笑
【今天壓力特別大,一直感覺有一種無形的力量扼住了喉嚨,讓我呼吸困難,脖子后面老有風。剛去了趟醫院,醫生認真的檢查之后,告訴我:你毛衣穿反了!】
**提出問題******
項目中如何處理異常???
解決問題
以下來自《Effective Java》這本書的筆記:
在這里復習下異常分類:
java中異常分為兩類:checked exception(檢查異常)和unchecked exception(未檢查異常),對于未檢查異常也叫RuntimeException(運行時異常).
對未檢查的異常(unchecked exception )的幾種處理方式:
1、捕獲
2、繼續拋出
3、不處理
對檢查的異常(checked exception,除了RuntimeException,其他的異常都是checked exception )的幾種處理方式:
1、繼續拋出,消極的方法,一直可以拋到java虛擬機來處理
2、用try...catch捕獲
注意,對于受檢異常必須處理,或者必須捕獲或者必須拋出
例如:
1)非受檢的:NullPointerException,ClassCastException,ArrayIndexsOutOfBoundsException,
ArithmeticException(算術異常,除0溢出)
2)受檢:Exception,FileNotFoundException,IOException,SQLException.
只針對異常的情況才使用異常
異常應該只用于異常情況下,它們永遠不應該用于正常控制流中。
錯誤案例:
try{
int i = 0;
while(true){
range[i++].climb();
}
}catch(ArrayOutOfBoundsException e){
//ArrayOutOfBoundsException 是非受檢異常,不應該捕獲,同時,也不應該
//在正常代碼中處理這種異常
}
改正:
for(Mountain m:range){
m.climb();
}
錯誤案例
try {
Iterable<Foo> i = collection.iterator();
while (true){
Foo foo = i.next();
}
}catch (NoSuchElementException e){
}
改正:
for(Iterable<Foo> i = collection.iterator();i.hasNext();){
Foo foo = i.next();
}
對可恢復的情況使用受檢異常,對編程錯誤使用運行時異常
標題已經說的很清楚了,下面簡單描述下:
在決定使用受檢的異常或是未受檢的異常時,主要原則是:如果期望調用者能夠適當地恢復,對于這種情況就應該使用受檢的異常。
有兩種未受檢的可拋出結構:運行時異常和錯誤,它們都是不需要也不應該被捕獲的可拋出結構。如果程序拋出未受檢的異常或者錯誤,往往就屬于不可恢復的情形,繼續執行下去有害無益。
優先使用標準的異常
專家級程序員與缺乏經驗的程序員一個最主要的區別在于,專家追求并且通常也能夠實現高度的代碼
代碼重用是值得提倡的,這是一條通用的規則,異常也不例外。
可以這么說,所有錯誤的方法調用都可以被歸結為非法參數或者非法狀態,即IllegalArgumentException 和 IllegalArgumentException
拋出與抽象相對應的異常
異常轉義:更高層的實現應該捕獲底層的異常,同時拋出可以按照高層抽象進行解釋的異常。
例如:
try{
//use lower-level abstraction to do our bidding
...
}catch(LowerLevelException e){
throw new HigherLevelException(...);
}
public void uploadImageFile(String imagePath) {
try {
/上傳圖片文件
}catch(IOException e) {
//把原始異常信息記錄到日記中(便于排錯)
throw new 異常構造方法();
}
}
異常鏈:將異常發生的原因一個傳一個串起來,即把底層的異常信息傳給上層,這樣逐層拋出.
try {
lowLevelOp();
}catch (LowLevelException le) {
throw (HighLevelException)
new HighLevelException().initCause(le);
}
總而言之,如果不能阻止或者處理來自更底層的異常,一般的做法是使用異常轉譯,除非底層方法碰巧可以保證它跑車的所有異常也適合才可以將異常從底層傳播到高層。異常鏈對高層和底層異常都提供了最佳的功能;它允許拋出適當的高層異常,同時又能捕獲底層的原因進行失敗分析。
每個方法拋出的異常都要有文檔
始終要單獨地聲明受檢的異常,并且利用Javadoc的@throws標記,準確地記錄下拋出每個異常的條件。
具體可以參考這篇文章:檢查異常和未檢查異常不同之處
總而言之,要為你編寫的每個方法所能拋出的每個異常建立文檔。對于未受檢和受檢的異常,以及對于抽象的和具體的方法都一樣。要為每個受檢異常提供單獨的throws子句,不要為未受檢的異常提供throws子句。如果沒有為可以拋出的異常建立文檔,其他人就很難或者根本不可能有效地使用你的類或者接口。
在細節消息中包含能捕獲失敗的信息
為了捕獲異常,異常的細節信息應該包含所有“對該異常有貢獻”的參數和域的值。
例如:
/**
* Constructs an <code>IndexOutOfBoundsException</code> with the
* specified detail message.
*
* @param s the detail message.
*/
//這個是IndexOutOfBoundsException這個異常的構造器
public IndexOutOfBoundsException(String s) {
super(s);
}
期望:
/**
* @param lowerBound
* @param upperBound
* @param index
*/
//通過改造后的異常可以包含足夠的能捕獲失敗的信息
public IndexOutOfBoundsException(int lowerBound,int upperBound,int index){
super("Lower bound: " + lowerBound +
",Upper bound: " + upperBound +
", Index:" + index);
this.lowerBound = lowerBound;
this.upperBound = upperBound;
this.index = index;
}
努力使失敗保持原子性
失敗原子性:失敗的方法調用應該使對象保持在被調用之前的狀態。
對于可變對象上執行操作的方法,獲得失敗原子性最常見的辦法是,在執行操作之前檢查參數的有效性。這可使得在對象的狀態被修改之前,先拋出適當的異常。例如:
public Object pop(){
//如果取消對size檢查,會導致size域保持不一致的狀態
if(size == 0){
throw new EmptyStackException();
}
Object result = elements[--size];
elements[size] = null;//
return result;
}
另外一種獲得失敗原子性的辦法是,調整計算處理過程的順序,使得任何可能會失敗的計算部分都在對象狀態被修改之前發生。
最后一種獲得失敗原子性的辦法是,在對象的一份臨時拷貝上執行操作,當操作完成之后,再用臨時拷貝中的結果代替對象的內容。
不要忽略異常
當API的設計者聲明一個方法將拋出某個異常的時候,他們等于正在視圖說明某些事情。所有請不要忽略它!
例如:
try{
...
}catch(SomeException e){
}
上面的例子中,是一個空的catch塊,空的catch塊會使異常達不到應有的目的,
讀書感悟
來自宗白華《美學散步》
- 中國的建筑、園林、雕塑中都潛伏著音樂感——即所謂“韻”。西方有的美學家說:一切的藝術都趨向于音樂。這話是有部分真理的。
- 一切藝術的美,以至于人格的美,都趨向于玉的美:內部有光澤,但是含蓄的光采,這種光彩是極絢爛又極平淡。
- 音樂領導我們去把握世界生命萬千形象里最深的節奏的起伏。
其他
如果有帶給你一絲絲小快樂,就讓快樂繼續傳遞下去,歡迎轉載,點贊,頂,歡迎留下寶貴的意見,多謝支持!