2016-09-22 168 views
1

爲什麼ByteArrayOutputStreamclosethrows IOException一起聲明? 首先,事實上它不能扔任何東西,因爲它的身體是空的。其次,它在法律上不能拋出任何東西,因爲它的文檔說「關閉一個ByteArrayOutputStream不起作用」。爲什麼ByteArrayOutputStream.close()拋出IOException?

這不是(非重要,但仍然)有點小錯誤嗎?

是的,我知道它的超類OutputStream執行Closableclose方法允許投擲IOException。但是沒有人禁止用close方法覆蓋它(在ByteArrayOutputStream中),並且沒有throw規範。 (即使覆蓋更拋出法用投擲少法在一些古老的版本的Java禁止,改變ByteArrayOutputStreamclose定義現在不會是不兼容的變化。)

+2

如果定義改變它趕上IOException異常將得到編譯錯誤,現有代碼'無法到達catch塊爲IOException。這個異常永遠不會從try語句體中拋出。 – saka1029

+0

@ saka1029:我想,你走在正確的軌道上。 – Holger

+0

@ saka1029,你是對的(我認爲這會導致警告,而不是錯誤)。 – Sasha

回答

2

最合理的解釋(除監督)是兼容性。回到Java 1.1,ByteArrayOutputStreamdid not override close(),所以它繼承了OutputStream的方法,它聲明瞭IOException。那時候,這可能是一個疏忽。也許,開發者認爲這是不必要的,因爲無論如何,沒有人會在ByteArrayOutputStream上調用close()。但是文件缺乏關於呼叫close()是不必要的明確聲明。

由於Java 1.2又名Java 2,ByteArrayOutputStreamdoes override close()。但是刪除throws子句將導致在ByteArrayOutputStream上調用close()的代碼,並在try塊內的任何其他位置未引發異常時捕獲檢查的IOException以產生編譯時錯誤。由於這不會影響二進制兼容性,因此考慮到源代碼級別對影響程度有多大影響後會發生多大變化,這可能看起來很奇怪。

但是這個決定是做了很長一段時間。也不清楚,爲什麼要添加覆蓋,因爲繼承的空操作已經足夠,並且覆蓋不會改變簽名,也不會在該版本中包含有用的文檔改進,即不需要關於close()的說明。最合理的解釋是,它添加了刪除throws子句的意圖,但後來發現不兼容性是某些現有代碼的問題。

最後,刪除它並不重要。如果您的編譯時類型爲ByteArrayOutputStream,則知道您不需要撥打close()。在其他情況下,即如果編譯時類型是更普遍的OutputStream,你必須close()並辦理申報IOException ...

+0

我明白,刪除它並不重要。 – Sasha

+0

實際上,答案的主要部分是由@ saka1029引入的:我不知道* remove * throws子句真的會引入不兼容。我認爲這個事實(刪除一個throws子句可能會引入源不兼容;「無法訪問的catch塊...」是一個錯誤,而不是一個警告)本身就是一個錯誤。 – Sasha

+0

@ saka1029的聲明是一條評論(不是答案),所以我不能接受它(儘管它首先出現並且很簡潔,所以我非常想這麼做)。 – Sasha

相關問題