下面的方法將乙個檔案拷貝到另乙個檔案,並且被設計為要關閉它所建立的每乙個流,即使它碰到i/o錯誤也要如此。遺憾的是,它並非總是能夠做到這一點。為什麼不能呢,你如何才能訂正它呢?
static void copy(string src, string dest) throws ioexception finally}
這個程式看起來已經面面俱到了。其流域(in和out)被初始化為null,並且新的流一旦被建立,它們馬上就被設定為這些流域的新值。對於這些域所引用的流,如果不為空,則finally語句塊會將其關閉。即便在拷貝操作引發了乙個ioexception的情況下,finally語句塊也會在方法返回之前執行。出什麼錯了呢?
問題在finally語句塊自身中。close方法也可能會丟擲ioexception異常。如果這正好發生在in.close被呼叫之時,那麼這個異常就會阻止out.close被呼叫,從而使輸出流仍保持在開放狀態。
請注意,該程式違反了謎題36的建議:對close的呼叫可能會導致finally語句塊意外結束。遺憾的是,編譯器並不能幫助你發現此問題,因為close方法丟擲的異常與read和write丟擲的異常型別相同,而其外圍方法(copy)宣告將傳播該異常。
解決方式是將每乙個close都包裝在乙個巢狀的try語句塊中。下面的finally語句塊的版本可以保證在兩個流上都會呼叫close:
} finally catch (ioexception ex)if (out != null)
try catch (ioexception ex)
} }
從5.0版本開始,你可以對**進行重構,以利用closeable介面:
} finally總之,當你在finally語句塊中呼叫close方法時,要用乙個巢狀的try-catch語句來保護它,以防止ioexception的傳播。更一般地講,對於任何在finally語句塊中可能會丟擲的被檢查異常都要進行處理,而不是任其傳播。這是謎題36中的教訓的一種特例,而對語言設計著的教訓情況也相同。private static void closeignoringexception(closeable c) catch (ioexception ex)
}}
《Java解惑》陷阱和缺陷的目錄
陷阱和缺陷的目錄 一 詞彙問題 1 字母l在許多字型中都與數字1相像。2 負的十六進製制字面常量看起來像是正的。3 八進位制字面常量與十進位制字面常量相像。4 ascii字元的unicode轉義字元容易令人迷茫。5 反斜槓必須被轉義,即使是在注釋中。6 塊注釋不要巢狀。二 整數運算 1 操作符的非零...
java之IO流 位元組流和字元流
file類是對檔案操作的類。在windows和非windows系統,目錄分隔符是不同的 windows 採用 非windows 採用 絕對路徑 從磁碟的根目錄開始,一級一級直到找到這個檔案 c users admin desktop abc.txt 相對路徑 以某乙個檔案作為參照,相對於這個檔案的路...
Java 位元組流和字元流(輸入流和輸出流)
什麼是位元組流?位元組流 傳輸過程中,傳輸資料的最基本單位是位元組的流。什麼是字元流?字元流 傳輸過程中,傳輸資料的最基本單位是字元的流。字元編碼方式不同,有時候乙個字元使用的位元組數也不一樣,比如ascll方式編碼的字元,佔乙個位元組 而utf 8方式編碼的字元,乙個英文本元需要乙個位元組,乙個中...