
今年有個(gè)目標(biāo)之一就是提升團(tuán)隊(duì)代碼的質(zhì)量,所以時(shí)常會(huì)思索如何把這件事做到更好,不想教條主義,也不想搞出一個(gè)代碼規(guī)范,強(qiáng)制團(tuán)隊(duì)照著做,落地的效果不好,反而把大家的積極性給弄沒(méi)了。所以我的原則是,我們一起看看什么事是我們不能做的,排除掉,剩下的就是我們可以做的,同時(shí)真正搞清楚問(wèn)題在哪里,而不是簡(jiǎn)單的模仿。從我個(gè)人的經(jīng)驗(yàn)看,代碼優(yōu)化中最重要的一點(diǎn)就是對(duì)異常情況的處理。今天,我就借這個(gè)話(huà)題,談?wù)勅绾蝸?lái)優(yōu)化我們的代碼。
坑1:捕捉異常不做處理
如下段代碼所示,不知道各位在自家的代碼中見(jiàn)過(guò)多少,我是期望大家不要遇見(jiàn)。且不說(shuō)printStackTrace()這樣的代碼就不應(yīng)該出線(xiàn)在正式的上線(xiàn)代碼中,不做處理本身這會(huì)導(dǎo)致業(yè)務(wù)的潛在問(wèn)題被隱藏了,所以這個(gè)坑是我認(rèn)為異常處理中最糟糕的一點(diǎn)。
try
{
....
}
catch(Exception ex)
{
ex.printStackTrace();
System.out.println(XXX);
}
對(duì)于異常的捕捉處理,遵循以下的流程:
處理該異常,執(zhí)行具體的邏輯處理,加上必要的系統(tǒng)日志記錄 (log4j,logcat ...)。
涉及其他系統(tǒng)或者上一級(jí)系統(tǒng),需要轉(zhuǎn)換成對(duì)應(yīng)的消息通知相關(guān)系統(tǒng)。上一級(jí)是前端,需要轉(zhuǎn)換成前端可以“讀懂”的錯(cuò)誤提示。
無(wú)法處理該異?;蛘咴摦惓P枰弦患?jí)統(tǒng)一處理,Throw out該異常。
坑2:不處理資源釋放
還是見(jiàn)代碼說(shuō)話(huà),如果append出錯(cuò),那么IO流就不會(huì)被關(guān)掉,那么最終就會(huì)導(dǎo)致整個(gè)程序因?yàn)橐绯霰赖簟?/p>
FileWriter fileWriter = null;
try
{
fileWriter = new FileWriter("");
fileWriter.append(item.toString());
fileWriter.close();
}
catch (IOException e)
{
...
}
在使用文件、IO流、數(shù)據(jù)庫(kù)連接等不會(huì)自動(dòng)釋放的資源時(shí),應(yīng)該在使用完畢后馬上將其關(guān)閉。關(guān)閉資源的代碼try...catch...finally的finally內(nèi)執(zhí)行,否則就可能因?yàn)镋xception的原因造成資源無(wú)法釋放。
坑3:對(duì)異常不進(jìn)行分類(lèi)處理
代碼中,最容易看到的一種情況就是設(shè)定catch的異常類(lèi)型是Exception, 并且只有一套處理邏輯, 如下:
try{
...
}
catch (Exception e){
...
}
這里的問(wèn)題主要有以下兩點(diǎn):
1. catch的不同Exception,可能需要執(zhí)行不同的處理邏輯,一個(gè)catch要同時(shí)處理所有邏輯就很難實(shí)現(xiàn)。
2.?由于是捕捉的基類(lèi)Exception, 那么RuntimeException也會(huì)被捕捉到,如果稍微不注意的話(huà),RuntimeException最終沒(méi)有任何實(shí)際處理,代碼中的真正錯(cuò)誤被掩蓋掉了。
所以,正確的做法應(yīng)該是按照具體的異常進(jìn)行分類(lèi)處理, ?例如:
try{
...
}
catch (FileNotFoundException e){
// alert that the specified file
// does not exist
}
catch (EOFException e){
// alert that the end of the file
// was reached
}
catch (ObjectStreamException e){
// alert that the file is corrupted
}
catch (IOException e){
// alert that some other I/O
// error occurred
}
坑4:將大段代碼放進(jìn)一個(gè)Try-Catch中
有時(shí)可以看到,一些代碼的作者恨不得把整個(gè)函數(shù)里的實(shí)現(xiàn)代碼都放入單個(gè)try中,原因就在于為了圖省事,不愿花時(shí)間分析一大塊代碼中哪幾行代碼會(huì)拋出什么異常、異常的具體類(lèi)型是什么,應(yīng)該如何處理。這樣的做法導(dǎo)致異常發(fā)生后,后續(xù)調(diào)試找問(wèn)題更麻煩,一大段代碼中有太多的地方可能拋出Exception。這樣的做法導(dǎo)致,很難去統(tǒng)計(jì)和判斷要catch哪一些類(lèi)型的Exception, 只能寫(xiě)一個(gè)粗糙的Exception, ?又掉進(jìn)我們說(shuō)的第3個(gè)坑里。
一點(diǎn)總結(jié)
在和大家一起分析了上面的異常坑后,如果未來(lái)我們想避免踩進(jìn)一個(gè)異???,編寫(xiě)異常代碼可以遵循以下三個(gè)點(diǎn):
1. 出了什么錯(cuò)?
2. 在哪出的錯(cuò)?
3. 為什么出錯(cuò)?
更多文章,請(qǐng)手動(dòng)搜索微信公眾號(hào)【架構(gòu)?!浚?ForestNotes