int與byte的區別


Java中涉及byte、short和char類型的運算操作首先會把這些值轉換為int類型,然后對int類型值進行運算,最后得到int類型的結果。因此,如果把兩個byte類型值相加,最后會得到一個int類型的結果。如果需要得到byte類型結果,必須將這個int類型的結果顯式轉換為byte類型。例如,下面的代碼會導致編譯失敗:
class BadArithmetic
{
static byte addOneAndOne()
{
byte a = 1;
byte b = 1;
byte c = (a + b);
return c;
}
}

當遇到上述代碼時,javac會給出如下提示:
type.java:6: possible loss of precision
found : int
required: byte
byte c = (a + b);
error

為了對這種情況進行補救,必須把a + b所獲得的int類型結果顯式轉換為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位長的。。。恩。。。你明白我的意思。你想對它們進行相加運算。在這個時候你的作用就很明顯了,當你對虛擬機說把它們倆給我相加成一個整數,那么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虛擬機會明白你的意思。


public class Test {
public static void main(String[] args) {
int a=35461;
System.out.println(Test.byte2int(Test.int2byte(a)));
}

/**
* 將int轉化成byte[]
*
* @param res 要轉化的整數
* @return 對應的byte[]
*/
public static byte[] int2byte(int res) {
byte[] targets = new byte[4];
targets[0] = (byte) (res & 0xff);// 最低位
targets[1] = (byte) ((res >> 8) & 0xff);// 次低位
targets[2] = (byte) ((res >> 16) & 0xff);// 次高位
targets[3] = (byte) (res >>> 24);// 最高位,無符號右移。
return targets;
}

/**
* 將byte[]轉化成int
* @param res 要轉化的byte[]
* @return 對應的整數
*/
public static int byte2int(byte[] res) {
int targets = (res[0] & 0xff) | ((res[1] << 8) & 0xff00) | ((res[2] << 24) >>> 8) | (res[3] << 24);
return targets;
}

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM