自從JDK7更新之后,新增了二進制變量的表示,支持將整數類型用二進制來表示,用0b開頭;
例如: byte b= (byte) 0b1000_0001;
short s = (short) 0b1000_0000_0000_0001;
新手在這個時候會遇到一個問題,為啥byte b=0b100_00001會報錯(cannot convert from int to byte)
而short b=0b100_00001又不會呢?既然java底層默認0b100_00001是int類型,為什么short可以呢?
有的人說是byte是字節數據類型,short是短整數據類型,個人認為不太准確。所以我們在做個試驗:
試驗1:short b=0b100_00001;//正常賦值;
short s=0b1000_0000_0000_0001;//系統報錯(cannot convert from int to byte);
這個結果出來想必大家都有些眉目了,在二進制中最高位被定義為符號位,byte共有8個比特位,我們給它
0b0000_0001時,最高位0系統無法判斷是 實際數值 還是 符號位數值 。如果我們加上(byte),則系統認為
此時的0是符號位,可以賦值;如果沒有加(byte),則認為是實際數值,然而byte類型只有8個比特位,無位置
表示符號位,因此溢出報錯。
試驗2:byte b=0b0000_0001;// 正常賦值
byte b=0b1000_0000;//報錯
再次印證了上面的推理,默認最高位是實際數值,超出位寬報錯。
-----------------------------------------------------------------黃金分割線---------------------------------------------------------------------
問題2:
byte a=(byte)0b1111_1111+0b0000_0001; ---> 0 //運行結果為0
有人解釋道0b0000_0001為int類型,而(byte)0b1111_1111為byte類型,運算時會轉為int類型運算,即為:
0000_0000_0000_0000_0000_0000_1111_1111
+
0000_0000_0000_0000_0000_0000_0000_0001
||
0000_0000_0000_0000_0000_0001_0000_0000
|| 轉為byte類型,直接截取后8位
0000_0000 = 0
那么又有人問了:
int a=(byte)0b1111_1111+0b0000_0001; 0 //運行結果同樣為0,為什么不是256
按照上面的意思被賦值變量a屬於int類型,既然是按照int類型運算,結果就不用轉換了嘛,直接賦值不就行啦?
我們在看幾組試驗:
1 、 byte a=(byte)0b0000_0001+0b1111_1111; -->報錯 //cannot convert from int to byte
int a=(byte)0b0000_0001+0b1111_1111; -->256 正常賦值
2 、 byte a=(byte)0b1111_1111+(byte)0b0000_0001; --> 0
int a=(byte)0b1111_1111+(byte)0b0000_0001; --> 0
3、 byte a=(byte)(0b1111_1111+0b0000_0001); --> 0
int a=(byte)(0b1111_1111+0b0000_0001); --> 0
4、 int a=0b1111_1111+0b0000_0001; --> 256
第一組報錯從第一個問題可以推出,0b1111_1111超出了等號左邊的byte類型范圍,所以才會報錯。
我們有三種推斷:
第一、如果是都轉為byte類型進行運算,那會考慮到符號位,多余正溢出,超出位寬自然舍棄,相加結果應為0b1000_0000,結果應為-128才對
顯然結果不是這樣的,因此這種推斷錯誤;
第二、如果是都轉為int類型進行運算,然后把值賦值給等號左邊,這種推論試驗2中int a=0,說不通,因此這種推斷錯誤;
第三、運算按照java直接值得規則,數值類型進行算數運算時,所有參與算數運算的數都會自動轉換為參與運算的最大類型,得到的值也是該類型
我們一一驗證補碼運算的結果{(byte)0b1111_1111對應的原碼為1000_0001即為-1,而0000_0001位1,相加結果為0},以上問題都可以推理出來,
因此,第三種推論是正確的,打完收工。