2014-01-29 112 views
4

也許有人可以幫助我理解,因爲我覺得我錯過了一些可能會影響我的程序運行效果的東西。爲什麼ByteArrayOutputStream使用int?

我正在使用ByteArrayOutputStream。除非我錯過了一些巨大的東西,這個類的重點是創建一個byte []數組用於其他用途。

但是,BAOS上的「簡單」寫入函數不是一個字節的int(ByteArrayOutputStream.write)。

根據這個(Primitive Data Types)頁面,在Java中,int是一個32位數據類型,一個字節是一個8位數據類型。

如果我寫這篇文章的代碼...

int i = 32; 
byte b = i; 

我得到一個關於需要改變這種可能有損轉換警告...

int i = 32; 
byte b = (byte)i; 

我真的很困惑寫( int)...

+1

請注意,這是'OutputStream.write'確定此,不是真的'ByteArrayOutputStream'。 –

+0

Yep ByteArrayOutputStream非常受限於它的父類。 –

+0

使用'byte'數據類型除了'byte []'的形式以外,可以說是一個壞主意。 「短」,恕我直言,也是如此。認爲字節和短是必要的邪惡,這只是讓你閱讀和編寫奇怪的二進制數據格式。不要使用字節/短變量,方法參數或返回類型。 (不,你不會以任何實質性的方式節省空間(除非是罕見的情況),而且你的代碼實際上可能會變慢。) – Ingo

回答

4

ByteArrayOutputStream只是覆蓋了在OutputStream中聲明的抽象方法。所以真正的問題是爲什麼OutputStream.write(int)是這樣聲​​明的,當它的目標是寫一個字節到流。流的實現在這裏是無關緊要的。

你的直覺是正確的 - 在我看來,這是一個破碎的設計。是的,它會丟失數據,如文檔中明確指出的那樣:

要寫入的字節是參數b的八個低位。 b的24個高位被忽略。

如果這是write(byte)會更合理(在我看來)。唯一的缺點是,你不能再用文字值稱之爲無鑄造:

// Write a single byte 0. Works with current code, wouldn't work if the parameter 
// were byte. 
stream.write(0); 

這看起來不錯,但不是 - 因爲字面0類型爲int,這是不隱式轉換到byte。你不得不使用:

// Ugly, but would have been okay with write(byte). 
stream.write((byte) 0); 

對於我來說,這不是一個好足夠的理由來設計API事情是這樣的,但這是我們所擁有 - 既然Java 1.0中有過。不幸的是,現在無法修復它,因爲它不是一個突破性的改變。

+0

Java中的字節是有符號的,所以如果方法以'byte'作爲參數,我們不能'stream.write(0xFF) '並獲得預期的全部字節。現在爲什麼java不支持無符號字節...... –

+0

@JoshuaTaylor Java實際上支持將int類型的整數類型解釋爲無符號,甚至在某種程度上甚至是無符號長整型。這是一個非常明智的決定,不明確支持這些東西。真正需要未簽名的人(這非常罕見)將不得不研究一下位和移位操作符。所以呢? – Ingo

+0

@JoshuaTaylor:你可以做'stream.write((byte)0xff'),並且會發生正確的事情。 –

5

爲了便於在0x7F以上的無符號字節發生。整數將被默默縮小以寫入。事實上,代碼does that(byte)強制轉換。

由於英戈指出:

一個可能的原因可能是寫字節將最經常出現一些操作,可自動轉換其操作數爲int [,像一些位運算的結果。因此,代碼將被拋到字節,這不會增加理解。

+0

這不是完全清楚爲什麼它不可能是一個'byte'參數雖然 - 來電者可以很容易地施放,如果他們想... –

+0

@JonSkeet中的Java API的許多設計決策是這樣的,它是很難找到他們背後的理性原因。事情的實質是該方法接受一個int並在其中進行明確的轉換。 – hexafraction

+0

這就是* what *的事實,但問題是爲什麼*。我同意你很難在這裏找到一個理由 - 但只是意味着我們不知道答案的疑問,有人問... –

0

這主要是因爲Java虛擬機模型的堆棧恨byte,但喜歡int該堆棧使用32位插槽,其大小與int相匹配。

但是,您會注意到java * does * like byte[]參考文獻。但那是因爲數組的內容存儲在堆中(而不是堆棧)。每當一個具體byte被尋址並移動到堆棧(在bipushsipush操作碼),然後立即將它們轉換爲整數。

但有時java的實際使用257(!)值。當InputStream#read()返回256個值時,但是當它沒有內容時,它將返回一個-1值。或者,它可能會拋出一個EOFException(就像其他一些方法一樣),但java中異常緩慢。

儘管您不需要OutputStream#write的值-1它是一致的,並且它減少了投射。但是,是的,這也是一種誤導。

相關問題