byte

最近因爲在做金融項目,裏面對byte的操作要求比較多,所以在這裏整理了一下關於Java中的byte類型。

Java虛擬機中沒有byte類型
恩。。。怎麼說呢,個人感覺這個說法有點兒唬人的意思。的確,當這個想法剛剛出現在我的腦海中的時候我覺得也有些胡扯,畢竟byte類型就在那裏,怎麼能說Java虛擬機中沒有byte類型呢?

好吧,我來稍稍的解釋一下。Java虛擬機對基本類型的操作基本都是在棧上完成的(這個是可信的,因爲不是我說的)。我們知道,Java在處理一個語句的時候,首先它會先把用到的操作數壓到棧中,然後再從棧中彈出進行計算,最後將結果再壓回到棧中。任何對byte的操作也會如此。因此,Java對byte類型操作之前會將其壓入到棧中。實際上,Java壓入棧的不是byte類型,而是一個標準的int類型(32位,byte是8位),也就是說,Java虛擬機將我們短小可愛的byte類型壓入棧之前,會先把它拉長成int類型再壓棧。(不過事實上在壓棧之前也是int類型)這樣一來,我們不管是在棧裏還是從棧裏彈出的byte類型實際上都是用int的長度存儲的。這也就是我爲什麼說,Java虛擬機中沒有byte類型。因爲它們都被變成了int。

int?還是byte?
這麼說來在Java虛擬機中處理來處理去的都是32位長的int,那麼byte怎麼辦?換句話說,如果我們看到一個32位的int,那我們應該管它叫int呢還是叫byte呢?(這句話有些拗口,我會在下次換一種描述的)

對於這個問題,我個人的答案是你叫丫蝦米丫就是蝦米。舉個例子來說吧:現在棧頂端有兩隻。。。恩。。。32位長的。。。恩。。。你明白我的意思。你想對它們進行相加運算。在這個時候你的作用就很明顯了,當你對虛擬機說把它們倆給我相加成一個整數(int),那麼Java虛擬機會彈出這兩個東西,然後相加,將結果以int類型壓回到棧中。但是如果你對虛擬機說:把這兩個byte相加成一個byte或者把它們倆相加成一個byte,那麼Java虛擬機還是會彈出這兩個東西相加,只不過前面那句會先將它們倆轉換成byte再變成int,然後相加;而後面那句會直接相加。兩句的最後結果都是將相加的和先轉換成byte然後在變成int壓入棧中。

類型轉換
那麼,類型轉換呢?這個總該是一個byte了吧!

可惜,我只能說類型轉換的過程中會出現真正的byte,但是它活不到最後就被拉長了。舉個例子吧,看看下面我從有意義的程序中找出的兩句毫無意義的代碼吧:

int a = 1;
byte b = (byte)a;

好吧,我承認會這麼寫的代碼,程序也不會有意義到哪兒去。但是我們就事論事。當我剛開始看到這個的時候,我非常興奮的認爲上面的那個變量b總應該是byte了吧。如果你和我一樣,那麼恭喜你離天才又進了一步。

我只能說答案是否定的。不是爲了打擊你,而確確實實是否定的。是的,第二句在執行的時候確實產生了一個byte,但是很不幸,它沒能活到最後。最終它被拉長成了int壓入了棧中,用來做爲byte變量b的值。雖然它被拉長成了32位的int,但是畢竟它是byte來的,所以身上還是有byte的血統的。怎麼說呢,那就是它是被虛擬機帶着符號擴展出來的。這個很好理解,byte本身就是8位0或者1的組合,你就是把8位上每一位0或者1拉的再長,充其量也就是長的長一些的0或者1的byte。所以要想變成32位,你得給byte填補24位進去。那麼這24位從哪裏來呢?Java虛擬機的做法就是從byte的符號位(也就是最高位)來。這就是所謂的帶符號擴展。就拿上面的程序舉例子吧,將1壓縮成byte用二進制來看是00000001,這個我想大家都不陌生。接下來就是擴展,我們byte的符號位是正,也就是0,那麼Java虛擬機就會用0來填充剩下的24位,結果就是00000000000000000000000000000001。自己數一下看我是不是漏掉了。

大家可能覺得我舉的例子有些太簡單了,好吧,我來說一個難的。讓byte變量b等於-1。當然,不是簡簡單單的從-1的int類型變成-1的byte類型,而是找一個正整數的int類型,讓Java虛擬機截短成-1的byte類型。那麼這個正整數是幾呢?說實話,我拿高級計算器試了一天,最後從google上找到了它:2147483647。只要把上面語句中a的值改成這個,byte變量b的值就會是-1。非常簡單,我覺得不需要解釋。
。。。
。。。
對不起,我有點兒得瑟和臭屁了。我還是解釋一下吧:那個2147483647整數的二進制是這樣的:01111111111111111111111111111111,仔細數,是32位。現在我們要把它強制轉換成byte,只有8位,所以Java虛擬機不假思索的給咱們砍掉24位,剩下8位都是1:11111111,這個當然就是那個-1了。什麼?你說不是?是-127?不不不不,不要忘了,Java虛擬機中使用補碼來表示的,你看到的是補碼。這次再算算,-1了吧。好了,接下來就是擴充回int類型了。簡單的把符號位複製24個出來就好了,結果就是11111111111111111111111111111111。這個是幾?自己算吧。

總結
好了,說了這麼多,我們也看到了,雖然Java虛擬機中的操作數可以是一個byte,但是不管是運算也好還是類型轉換也好,最終的結果都是int。至於在執行過程中如何區別,那就全靠寫程序的人自己了。如果你自己都模棱兩可的話,不要指望Java虛擬機會明白你的意思。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章