java try catch

一、參考為什么不建議用 try catch

try catch機制非常好。那些覺得try catch不行的人,是他們自己的水平有問題,無法理解這種機制。并且這群人寫代碼不遵守規(guī)則,喜歡偷懶,這才造成try catch不好的錯覺。

詳細解釋:
1.程序要健壯,必須要設(shè)計報錯機制。
最古老,也是最常見的,比如:
bool CreateFile( );
//如果創(chuàng)建文件失敗就返回false,否則返回true。
這種報錯方式,顯然不好。因為它沒有給出產(chǎn)生錯誤的具體原因。

2.改進:一個函數(shù)或過程,會因為不同的原因產(chǎn)生錯誤,報錯機制必須要把這些錯誤原因進行區(qū)分后,再匯報。
比如:
int CreateFile():
//如果創(chuàng)建成功就返回1.
//如果是因為沒有權(quán)限,導(dǎo)致失敗,返回-1。
//如果是因為文件已經(jīng)存在,導(dǎo)致失敗,返回-2。
//如果是因為創(chuàng)建文件發(fā)生超時,導(dǎo)致失敗,返回-3。
這樣看上去,比【1】要好些,至少指出了比較具體的失敗原因,但是,還不夠。

3.很多情況下,函數(shù)需要把詳細的原因,用字符串的方式,返回:
<pre>
class Result
{
....int State;//同【2】
....string ErrorMessage;//如果失敗,這里將給出詳細的信息,如果有可能,應(yīng)該把建議也寫上去。
}

Result CreateFile();
//如果創(chuàng)建成功,返回的Result,State為1,ErrorMessage為null。
//如果是因為沒有權(quán)限,導(dǎo)致失敗,返回的Result,State為-1,ErrorMessage為"用戶【guest】沒有權(quán)限在【C:\】這個目錄下創(chuàng)建該文件。建議您向管理員申請權(quán)限,或者更換具有權(quán)限的用戶。"。
//如果是因為文件已經(jīng)存在,導(dǎo)致失敗,返回的Result,State為-2,ErrorMessage為"文件【C:\abc.txt】已經(jīng)存在。如果需要覆蓋,請?zhí)砑訁?shù):arg_overwrite = true"。
//如果是因為創(chuàng)建文件發(fā)生超時,導(dǎo)致失敗,返回的Result,State為-3,ErrorMessage為"在創(chuàng)建文件時超時,請使用chkdsk檢查文件系統(tǒng)是否存在問題。"。
</pre>
4.我個人推崇上面這種方式,完整,美觀。但是這種流程,容易與正常的代碼混在一起,不好區(qū)分開。因此,Java、C#等設(shè)計了try catch這一種特殊的方式:
<pre>
void CreateFile()
//如果創(chuàng)建成功就不會拋出異常。
//如果是因為沒有權(quán)限,導(dǎo)致失敗,會拋出AccessException,這個Exception的Msg屬性為"用戶【guest】沒有權(quán)限在【C:\】這個目錄下創(chuàng)建該文件。建議您向管理員申請權(quán)限,或者更換具有權(quán)限的用戶。"。
//如果是因為文件已經(jīng)存在,導(dǎo)致失敗,會拋出FileExistedException,這個Exception的Msg屬性為"文件【C:\abc.txt】已經(jīng)存在。如果需要覆蓋,請?zhí)砑訁?shù):arg_overwrite = true"。
//如果是因為創(chuàng)建文件發(fā)生超時,導(dǎo)致失敗,會拋出TimeoutException,這個Exception的Msg屬性為"在創(chuàng)建文件時超時,請使用chkdsk檢查文件系統(tǒng)是否存在問題。"。
</pre>
可見,上述機制,實際上是用不同的Exception代替了【3】的State。

這種機制,在外層使用時:
<pre>
try
{
....CreateFile( "C:\abc.txt" );
}
catch( AccessException e )
{
....//代碼進入這里說明發(fā)生【沒有權(quán)限錯誤】
}
catch( FileExistedException e )
{
....//代碼進入這里說明發(fā)生【文件已經(jīng)存在錯誤】
}
catch( TimeoutException e )
{
....//代碼進入這里說明發(fā)生【超時錯誤】
}
</pre>
對比一下【3】,其實這與【3】本質(zhì)相同,只是寫法不同而已。

5.綜上,我個人喜歡【3】這類面向過程的寫法。但很多喜歡面向?qū)ο蟮呐笥眩烙嫺矚g【4】的寫法。然而【3】與【4】都一樣。這兩種機制都是優(yōu)秀的錯誤處理機制。

6.理論說完了,回到正題,題注問:為什么不用try catch?
答:這是因為,很多菜鳥,以及新手,他們是這樣寫代碼的:
void CreateFile( )
//無論遇到什么錯誤,就拋一個 Exception,并且也不給出Msg信息。
這樣的話,在外層只能使用:
<pre>
try
{
....CreateFile( "C:\abc.txt" );
}
catch( Exception e )
{
....//代碼進入這里說明發(fā)生錯誤
}
</pre>
當(dāng)出錯后,只知道它出錯了,并不知道是什么原因?qū)е洛e誤。這同【1】。

以及,即使CreateFile是按【4】的規(guī)則設(shè)計的,但菜鳥在外層是這樣使用的:
<pre>
try
{
....CreateFile( "C:\abc.txt" );
}
catch( Exception e )
{
....//代碼進入這里說明發(fā)生錯誤
....throw Exception( "發(fā)生錯誤" )
}
</pre>
這種情況下,如果這位菜鳥的同事,調(diào)用了這段代碼,或者用戶看到這個錯誤信息,也只能知道發(fā)生了錯誤,但并不清楚錯誤的原因。這與【1】是相同的。

出于這些原因,菜鳥的同事,以及用戶,并沒有想到,造成這個問題是原因菜鳥的水平太差,寫代碼圖簡單省事。他們卻以為是try catch機制不行。

因此,這就導(dǎo)致了二逼同事,以及傻比用戶,不建議用try catch。

二、參考項目中到處都是try-catch是一種常態(tài)嗎

通常try/catch適用于以下場景:

  • 在代碼中對可預(yù)見而又無法掌控的情況進行處理。比如在SOCKET BIND時發(fā)現(xiàn)端口已經(jīng)被占用了、或者IO在打開文件時發(fā)現(xiàn)文件不存在,就需要在catch中做適當(dāng)?shù)奶幚肀苊獬绦騝rash掉;
  • 將問題向更上一層面?zhèn)鬟f,將處理權(quán)讓渡給caller。假如你寫了個ORM FRAMEWORK,在delete的時候發(fā)現(xiàn)外鍵關(guān)聯(lián)刪除失敗,F(xiàn)RAMEWORK不能擅自替上層的代碼決定該怎么辦,于是只好把DB的報的錯誤原樣(或者加層外衣)throw出來,調(diào)用者根據(jù)業(yè)務(wù)需要選擇處理方式;

除此之外,所有問題應(yīng)該由程序員主動判斷,就地解決。在規(guī)模比較大的軟件中,定義自己的Exception體系并正確、克制地使用try/catch,可以讓代碼變得易讀易維護還美觀。

傳遞給上層來解決例子如下:
<pre>
void handlearray(int a[]) throws Npe
{
if(a==null)
throw new Npe();
a[0]……//處理部分
}

上層:
try{
handlearray(a);
}catch(E… e)
{
//對a進行處理。
}
</pre>
這時候傳入數(shù)組為空,這個錯誤不是你當(dāng)前這個函數(shù)所能處理的,只能是拋給上層,也就是生成這個數(shù)組,或者能對這個數(shù)組負責(zé)的那部分代碼,讓上層去處理,上層去try cacth,并在catch中對異常處理,類庫中類似的像文件io的時候很多讀寫類都會拋出FileNotFoundException,也是一個道理,當(dāng)上層給我一個找不到的文件,那在我的io類中肯定無法處理你這個異常,只能拋到給我這個文件的那一層,讓那一層的代碼對這個問題進行反應(yīng)。

當(dāng)然有些時候不需要,比如:
<pre>
void makearray(int a[])
{
a=new int[];
……//生成部分
if(a==null)
……//處理部分,此處一般不用拋異常,直接可以在這一層處理掉。
}
</pre>
像這個就不一樣了,因為這次發(fā)生的問題是在我這一層代碼所能控制之內(nèi)的,所以我直接把問題處理掉就好了,沒必要給上層了。

為什么講“正確”并“克制”地使用?因為有些又蠢又懶的程序員喜歡這么干:

  1. 將函數(shù)所有代碼都放到try{}之中,哪怕 int i = 1這種賦值的都不放過。然后在catch里輸出一個錯誤信息就萬事大吉。這樣看起來是很省心哇,不用動腦子去分析哪里可能發(fā)生什么錯誤,反正所有錯誤都在catch的掌控之中;
  2. 用try/catch來控制流程。舉個簡單的例子,假設(shè)有這么個要求:
    將字符串轉(zhuǎn)換成數(shù)字,并返回該數(shù)字的絕對值,如果出錯了就返回-1. 于是乎,就能見到類似下面代碼的奇葩做法:
    <pre>
    int parse_number(const char* s){
    try{
    return abs(atoi(s));
    }catch(Exception){
    return -1;
    }
    }
    </pre>
    這多省事兒,不用考慮s是不是NULL、不用考慮s是不是包含非數(shù)字的字符、不用考慮s是不是超出int的取值范圍...我是個優(yōu)秀的程序員耶~~,我的代碼好簡潔。

try/catch和errno可以結(jié)合起來使用,二者不是非此即彼的關(guān)系,比如在某些場景下,可以將不確定的錯誤簡化歸納為固定的errno輸出,調(diào)用者直接檢查返回的errno即可,簡化了代碼,也減輕了負擔(dān)。比如某函數(shù),成功返回0,失敗返回-1:
<pre>
int foo(double d){
try{
do_something(d);
return 0;
}catch(Exception){
return -1;
}
}

void bar(double d){
int result = foo(d);
if(result == -1) return;
do_next_steps();
}
</pre>

三、細節(jié)

Java中try,catch,finally的用法
Java異常處理的組合方式:
1.try+catch
運行流程:運行到try塊中,如果有異常拋出,則轉(zhuǎn)到catch塊去處理。然后執(zhí)行catch塊后面的語句
2.try+catch+finally
運行流程:運行到try塊中,如果有異常拋出,則轉(zhuǎn)到catch塊,catch塊執(zhí)行完畢后,執(zhí)行finally塊的代碼,再執(zhí)行finally塊后面的代碼。
如果沒有異常拋出,執(zhí)行完try塊,也要去執(zhí)行finally塊的代碼。然后執(zhí)行finally塊后面的語句

Java finally語句到底是在return之前還是之后執(zhí)行?

網(wǎng)上有很多人探討Java中異常捕獲機制try...catch...finally塊中的finally語句是不是一定會被執(zhí)行?很多人都說不是,當(dāng)然他們的回答是正確的,經(jīng)過我試驗,至少有兩種情況下finally語句是不會被執(zhí)行的:

(1)try語句沒有被執(zhí)行到,如在try語句之前就返回了,這樣finally語句就不會執(zhí)行,這也說明了finally語句被執(zhí)行的必要而非充分條件是:相應(yīng)的try語句一定被執(zhí)行到。

(2)在try塊中有System.exit(0);這樣的語句,System.exit(0);是終止Java虛擬機JVM的,連JVM都停止了,所有都結(jié)束了,當(dāng)然finally語句也不會被執(zhí)行到。

四、檢查型異常和非檢查型異常

Paste_Image.png

上圖摘自Java 進階 之 檢查型異常與非檢查型異常

  • 直接繼承 Exception 的異常,屬于檢查型異常,必須用try語句塊進行處理或者把異常交給上級方法處理總之就是必須寫代碼處理它。如IOException,SQLException
  • 繼承自Runtime Exception或 Error 的是非檢查型異常,可以不用捕獲
五、throw 和 throws區(qū)別

1、throws出現(xiàn)在方法函數(shù)頭;而throw出現(xiàn)在函數(shù)體。
2、throws表示出現(xiàn)異常的一種可能性,并不一定會發(fā)生這些異常;throw則是拋出了異常,執(zhí)行throw則一定拋出了某種異常對象。
3、兩者都是消極處理異常的方式(這里的消極并不是說這種方式不好),只是拋出或者可能拋出異常,但是不會由函數(shù)去處理異常,真正的處理異常由函數(shù)的上層調(diào)用處理。

六、關(guān)于異常的面試問答
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,016評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內(nèi)容

  • 1 拋出 Exception,沒有 finally,當(dāng) catch 遇上 return 1 2public sta...
    織田信長閱讀 861評論 0 2
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,722評論 18 399
  • try...catch...finally由兩段代碼展開下面要討論的話題 try..catch...finally...
    snoweek閱讀 264評論 0 3
  • 當(dāng)夜入深處時,天地萬物寂靜,我們需要做的靜待署光,而此時美在靜靜地蔓延,沒有人知道,那些花何時爬滿了枯墻,就像沒有...
    水善萬物閱讀 146評論 0 0
  • 我今天仔細的在腦海里問了自己一個問題,你到底想不想結(jié)婚? 上課的時候,任課老師和周圍幾個同學(xué)不知道借由什么話題,引...
    鹿遇閱讀 403評論 0 1