色欲av一区久久精品_久久综合色综合色88_无码在线观看不卡_色黄视频网站_亚洲国产精品久久久久秋霞66

你竟然還在用 try–catch-finally

時(shí)間:2023-05-16

這是讀者Alice上星期特意給我發(fā)來(lái)的信息,真令我動(dòng)容。的確,上次的“我去”閱覽量杠杠的,幾個(gè)大號(hào)都轉(zhuǎn)載了,包括CSDN,次條當(dāng)天都1.5萬(wàn)閱覽。但比如“還認(rèn)為你有什么新特技,沒(méi)想到用的是Java13”這類批評(píng)的聲響也不在少數(shù)。
不過(guò)我的心一直很大。從我寫榜首篇文章至今,被噴的次數(shù)就好像頭頂上茂密的發(fā)量一樣,數(shù)也數(shù)不清。所以我決定再接再厲,帶來(lái)新的一篇“我去”。
這次不必長(zhǎng)途review了,由于咱們公司也復(fù)工了。這次review的代碼仍然是小王的,他編寫的大部分代碼都很美麗,嚴(yán)謹(jǐn)?shù)囊黄鹱⑨屢埠艿轿?,這令我十分滿足。但當(dāng)我看到他沒(méi)用try-with-resources時(shí),還是不由得破口大罵:“我擦,小王,你丫的居然還在用try–catch-finally!”
來(lái)看看小王寫的代碼吧。
publicclassTrycatchfinally{
publicstaticvoidmain(String[]args){
BufferedReaderbr=null;
try{
br=newBufferedReader(newFileReader(“/牛逼.txt”));
Stringstr=null;
while((str=br.readLine())!=null){
System.out.println(str);
}
}catch(IOExceptione){
e.printStackTrace();
}finally{
if(br!=null){
try{
br.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
}
咦,感覺(jué)這段代碼很完美無(wú)缺啊,try–catch-finally用得中規(guī)中矩,尤其是文件名牛逼.txt很亮。不必寫注釋都能明白這段代碼是干嘛的:在try塊中讀取文件中的內(nèi)容,并一行一行地打印到控制臺(tái)。假設(shè)文件找不到或者出現(xiàn)IO讀寫過(guò)錯(cuò),就在catch中捕獲并打印過(guò)錯(cuò)的倉(cāng)庫(kù)信息。最后,在finally中封閉緩沖字符讀取器目標(biāo)BufferedReader,有用杜絕了資源未被封閉的情況下造成的嚴(yán)峻功能成果。
在Java7之前,try–catch-finally的確是保證資源會(huì)被及時(shí)封閉的最佳辦法,無(wú)論程序是否會(huì)拋出反常。
可是呢,有經(jīng)歷的讀者會(huì)從上面這段代碼中發(fā)現(xiàn)2個(gè)嚴(yán)峻的問(wèn)題:
1)文件名“牛逼.txt”包含了中文,需求經(jīng)過(guò)java.net.URLDecoder類的decode()辦法對(duì)其轉(zhuǎn)義,不然這段代碼在運(yùn)轉(zhuǎn)時(shí)鐵定要拋出文件找不到的反常。
2)假設(shè)直接經(jīng)過(guò)newFileReader(“牛逼.txt”)創(chuàng)立FileReader目標(biāo),“牛逼.txt”需求和項(xiàng)目的src在同一級(jí)目錄下,不然同樣會(huì)拋出文件找不到的反常。但大多數(shù)情況下,(裝備)文件會(huì)放在resources目錄下,便于編譯后文件出現(xiàn)在classes目錄下,Java
為了處理以上2個(gè)問(wèn)題,咱們需求對(duì)代碼進(jìn)行優(yōu)化:
publicclassTrycatchfinallyDecoder{
publicstaticvoidmain(String[]args){
BufferedReaderbr=null;
try{
Stringpath=TrycatchfinallyDecoder.class.getResource(“/牛逼.txt”).getFile();
StringdecodePath=URLDecoder.decode(path,”utf-8″);
br=newBufferedReader(newFileReader(decodePath));
Stringstr=null;
while((str=br.readLine())!=null){
System.out.println(str);
}
}catch(IOExceptione){
e.printStackTrace();
}finally{
if(br!=null){
try{
br.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
}
運(yùn)轉(zhuǎn)這段代碼,程序就能夠?qū)⑽募械膬?nèi)容正確輸出到控制臺(tái)。但假設(shè)你對(duì)“整潔”這個(gè)詞心生神往的話,會(huì)感覺(jué)這段代碼十分臃腫,尤其是finally中的代碼,就好像一個(gè)灌了12瓶雪花啤酒的大肚腩。
網(wǎng)上看到一幅Python程序員調(diào)侃Java程序員的神圖,直接copy過(guò)來(lái)(侵刪),逗你一樂(lè):
何況,try–catch-finally至始至終存在一個(gè)嚴(yán)峻的危險(xiǎn):try中的br.readLine()有可能會(huì)拋出IOException,finally中的br.close()也有可能會(huì)拋出IOException。假設(shè)兩處都不幸地拋出了IOException,那程序的調(diào)試使命就變得復(fù)雜了起來(lái),到底是哪一處出了過(guò)錯(cuò),就需求花一番功夫,這是咱們不愿意看到的成果。
為了模擬上述情況,咱們來(lái)自定義一個(gè)類MyfinallyReadLineThrow,它有兩個(gè)辦法,分別是readLine()和close(),辦法體都是自動(dòng)拋出反常。
classMyfinallyReadLineThrow{
publicvoidclose()throwsException{
thrownewException(“close”);
}
publicvoidreadLine()throwsException{
thrownewException(“readLine”);
}
}
然后咱們?cè)趍ain()辦法中運(yùn)用try-finally的方式調(diào)用MyfinallyReadLineThrow的readLine()和close()辦法:
publicclassTryfinallyCustomReadLineThrow{
publicstaticvoidmain(String[]args)throwsException{
MyfinallyReadLineThrowmyThrow=null;
try{
myThrow=newMyfinallyReadLineThrow();
myThrow.readLine();
}finally{
myThrow.close();
}
}
}
運(yùn)轉(zhuǎn)上述代碼后,過(guò)錯(cuò)倉(cāng)庫(kù)如下所示:
Exceptioninthread”main”java.lang.Exception:closeatcom.cmower.dzone.trycatchfinally.MyfinallyOutThrow.close(TryfinallyCustomOutThrow.java:17)atcom.cmower.dzone.trycatchfinally.TryfinallyCustomOutThrow.main(TryfinallyCustomOutThrow.java:10)
readLine()辦法的反常信息居然被close()辦法的倉(cāng)庫(kù)信息吃了,這必然會(huì)讓咱們誤認(rèn)為要調(diào)查的目標(biāo)是close()辦法而不是readLine()——雖然它也是應(yīng)該懷疑的目標(biāo)。
但自從有了try-with-resources,這些問(wèn)題就迎刃而解了,只要需求開(kāi)釋的資源(比如BufferedReader)完成了AutoCloseable接口。有了處理方案之后,咱們來(lái)對(duì)之前的finally代碼塊進(jìn)行減肥。
try(BufferedReaderbr=newBufferedReader(newFileReader(decodePath));){
Stringstr=null;
while((str=br.readLine())!=null){
System.out.println(str);
}
}catch(IOExceptione){
e.printStackTrace();
}
你瞧,finally代碼塊消失了,取而代之的是把要開(kāi)釋的資源寫在try后的()中。假設(shè)有多個(gè)資源(BufferedReader和PrintWriter)需求開(kāi)釋的話,能夠直接在()中增加。
try(BufferedReaderbr=newBufferedReader(newFileReader(decodePath));
PrintWriterwriter=newPrintWriter(newFile(writePath))){
Stringstr=null;
while((str=br.readLine())!=null){
writer.print(str);
}
}catch(IOExceptione){
e.printStackTrace();
}
假設(shè)你想開(kāi)釋自定義資源的話,只要讓它完成AutoCloseable接口,并供給close()辦法即可。
publicclassTrywithresourcesCustom{
publicstaticvoidmain(String[]args){
try(MyResourceresource=newMyResource();){
}catch(Exceptione){
e.printStackTrace();
}
}
}classMyResourceimplementsAutoCloseable{
@Overridepublicvoidclose()throwsException{
System.out.println(“封閉自定義資源”);
}
}
代碼運(yùn)轉(zhuǎn)后輸出的成果如下所示:
封閉自定義資源
是不是很奇特?咱們?cè)趖ry()中只是new了一個(gè)MyResource的目標(biāo),其他什么也沒(méi)干,但偏偏close()辦法中的輸出句子執(zhí)行了。想要知道為什么嗎?來(lái)看看反編譯后的字節(jié)碼吧。
classMyResourceimplementsAutoCloseable{
MyResource(){
}
publicvoidclose()throwsException{
System.out.println(“封閉自定義資源”);
}
}publicclassTrywithresourcesCustom{
publicTrywithresourcesCustom(){
}
publicstaticvoidmain(String[]args){
try{
MyResourceresource=newMyResource();
resource.close();
}catch(Exceptionvar2){
var2.printStackTrace();
}
}
}
咦,編譯器居然自動(dòng)為try-with-resources進(jìn)行了變身,在try中調(diào)用了close()辦法。
接下來(lái),咱們?cè)谧远x類中再增加一個(gè)out()辦法,
classMyResourceOutimplementsAutoCloseable{
@Overridepublicvoidclose()throwsException{
System.out.println(“封閉自定義資源”);
}
publicvoidout()throwsException{
System.out.println(“緘默沉靜王二,一枚有趣的程序員”);
}
}
這次,咱們?cè)趖ry中調(diào)用一下out()辦法:
publicclassTrywithresourcesCustomOut{
publicstaticvoidmain(String[]args){
try(MyResourceOutresource=newMyResourceOut();){
resource.out();
}catch(Exceptione){
e.printStackTrace();
}
}
}
再來(lái)看一下反編譯的字節(jié)碼:
publicclassTrywithresourcesCustomOut{
publicTrywithresourcesCustomOut(){
}
publicstaticvoidmain(String[]args){
try{
MyResourceOutresource=newMyResourceOut();
try{
resource.out();
}catch(Throwablevar5){
try{
resource.close();
}catch(Throwablevar4){
var5.addSuppressed(var4);
}
throwvar5;
}
resource.close();
}catch(Exceptionvar6){
var6.printStackTrace();
}
}
}
這次,catch塊中自動(dòng)調(diào)用了resource.close(),而且有一段很要害的代碼var5.addSuppressed(var4)。它有什么用途呢?當(dāng)一個(gè)反常被拋出的時(shí)分,可能有其他反常由于該反常而被按捺住,從而無(wú)法正常拋出。這時(shí)能夠經(jīng)過(guò)addSuppressed()辦法把這些被按捺的辦法記錄下來(lái)。被按捺的反常會(huì)出現(xiàn)在拋出的反常的倉(cāng)庫(kù)信息中,也能夠經(jīng)過(guò)getSuppressed()辦法來(lái)獲取這些反常。這樣做的好處是不會(huì)丟失任何反常,方便咱們開(kāi)發(fā)人員進(jìn)行調(diào)試。
哇,有沒(méi)有想到咱們之前的那個(gè)比如——在try-finally中,readLine()辦法的反常信息居然被close()辦法的倉(cāng)庫(kù)信息吃了?,F(xiàn)在有了try-with-resources,再來(lái)看看作用和readLine()辦法一致的out()辦法會(huì)不會(huì)被close()吃掉。
在close()和out()辦法中直接拋出反常:
classMyResourceOutThrowimplementsAutoCloseable{
@Overridepublicvoidclose()throwsException{
thrownewException(“close()”);
}
publicvoidout()throwsException{
thrownewException(“out()”);
}
}
調(diào)用這2個(gè)辦法:
publicclassTrywithresourcesCustomOutThrow{
publicstaticvoidmain(String[]args){
try(MyResourceOutThrowresource=newMyResourceOutThrow();){
resource.out();
}catch(Exceptione){
e.printStackTrace();
}
}
}
程序輸出的成果如下所示:
java.lang.Exception:out()
atcom.cmower.dzone.trycatchfinally.MyResourceOutThrow.out(TrywithresourcesCustomOutThrow.java:20)atcom.cmower.dzone.trycatchfinally.TrywithresourcesCustomOutThrow.main(TrywithresourcesCustomOutThrow.java:6)Suppressed:java.lang.Exception:close()
atcom.cmower.dzone.trycatchfinally.MyResourceOutThrow.close(TrywithresourcesCustomOutThrow.java:16)atcom.cmower.dzone.trycatchfinally.TrywithresourcesCustomOutThrow.main(TrywithresourcesCustomOutThrow.java:5)
瞧,這次不會(huì)了,out()的反常倉(cāng)庫(kù)信息打印出來(lái)了,而且close()辦法的倉(cāng)庫(kù)信息上加了一個(gè)要害字Suppressed。一望而知,不錯(cuò)不錯(cuò),我喜歡。
總結(jié)一下,在處理必須封閉的資源時(shí),一直有限考慮運(yùn)用try-with-resources,而不是try–catch-finally。前者發(fā)生的代碼更加簡(jiǎn)練、清晰,發(fā)生的反常信息也更靠譜。答應(yīng)我好不好?別再用try–catch-finally了。

文章標(biāo)簽:

Copyright ? 2016 廣州思洋文化傳播有限公司,保留所有權(quán)利。 粵ICP備09033321號(hào)

與項(xiàng)目經(jīng)理交流
掃描二維碼
與項(xiàng)目經(jīng)理交流
掃描二維碼
與項(xiàng)目經(jīng)理交流
ciya68