2015-04-16 45 views
5

我有一個字節變量:爲什麼Java無符號位移位的負字節是如此奇怪?

byte varB = (byte) -1; // binary view: 1111 1111 

我想看到兩個最左邊位,做一個無符號右移 6位數:

varB = (byte) (varB >>> 6); 

但我得到-1好像它是int型,並得到只有我換了30!

我該如何解決這個問題,並只用6位數的班次得到結果?

+0

對'char','byte'或'short'的所有算術運算首先提升爲int。 – Radiodef

回答

8

原因是與位移時發生的數字提升int相關聯的符號擴展。在轉換之前,值varB被提升爲int。無符號位右移確實發生,但其影響被丟棄鑄造回byte,只保留最後8位時:

varB (byte)  : 11111111 
promoted to int : 11111111 11111111 11111111 11111111 
shift right 6 : 00000011 11111111 11111111 11111111 
cast to byte : 11111111 

您可以使用按位與運營商&掩蓋了移位前不需要的位。與0xFF位比較只保留8個最低有效位。

varB = (byte) ((varB & 0xFF) >>> 6); 

這裏現在發生了什麼:

varB (byte)  : 11111111 
promoted to int : 11111111 11111111 11111111 11111111 
bit-and mask : 00000000 00000000 00000000 11111111 
shift right 6 : 00000000 00000000 00000000 00000011 
cast to byte : 00000011 
4

因爲這就是如何在Java字節偏移在語言定義的:https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.19

的要點是小於int的類型會默默擴展爲int,轉移並縮小回來。

使您的單行有效等價的:

byte b = -1;  // 1111_1111 
int temp = b;  // 1111_1111_1111_1111_1111_1111_1111_1111 
temp >>>= 6;  // 0000_0011_1111_1111_1111_1111_1111_1111 
b = (byte) temp; // 1111_1111 

要改變只是你需要擴大轉換明確自己與無符號的語義字節(和收縮轉換需要手動是,太) :

byte b = -1;   // 1111_1111 
int temp = b & 0xFF; // 0000_0000_0000_0000_0000_0000_1111_1111 
temp >>>= 6;   // 0000_0000_0000_0000_0000_0000_0000_0011 
b = (byte) temp;  // 0000_0011