Java 位運算

一,Java 位運算java

1.表示方法:程序員

 在Java語言中,二進制數使用補碼錶示,最高位爲符號位,正數的符號位爲0,負數爲1。補碼的表示須要知足以下要求。
 (l)正數的最高位爲0,其他各位表明數值自己(二進制數)。
 (2)對於負數,經過對該數絕對值的補碼按位取反,再對整個數加1。數組

2.位運算符
 位運算表達式由操做數和位運算符組成,實現對整數類型的二進制數進行位運算。位運算符能夠分爲邏輯運算符(包括~、&、|和^)及移位運算符(包括>>、<<和>>>)。ui

1)左移位運算符(<<)能將運算符左邊的運算對象向左移動運算符右側指定的位數(在低位補0)。
2)「有符號」右移位運算符(>>)則將運算符左邊的運算對象向右移動運算符右側指定的位數。
「有符號」右移位運算符使用了「符號擴展」:若值爲正,則在高位插入0;若值爲負,則在高位插入1。編碼

3)Java也添加了一種「無符號」右移位運算符(>>>),它使用了「零擴展」:不管正負,都在高位插入0。這一運算符是C或C++沒有的。.net

4)若對char,byte或者short進行移位處理,那麼在移位進行以前,它們會自動轉換成一個int。
只有右側的5個低位纔會用到。這樣可防止咱們在一個int數裏移動不切實際的位數。
若對一個long值進行處理,最後獲得的結果也是long。此時只會用到右側的6個低位,防止移動超過long值裏現成的位數。
但在進行「無符號」右移位時,也可能遇到一個問題。若對byte或short值進行右移位運算,獲得的可能不是正確的結果(Java 1.0和Java 1.1特別突出)。
它們會自動轉換成int類型,並進行右移位。但「零擴展」不會發生,因此在那些狀況下會獲得-1的結果。對象

在進行位運算時,須要注意如下幾點。
  (1)>>>和>>的區別是:在執行運算時,>>>運算符的操做數高位補0,而>>運算符的操做數高位移入原來高位的值。
  (2)右移一位至關於除以2,左移一位(在不溢出的狀況下)至關於乘以2;移位運算速度高於乘除運算。
  (3)若進行位邏輯運算的兩個操做數的數據長度不相同,則返回值應該是數據長度較長的數據類型。
  (4)按位異或能夠不使用臨時變量完成兩個值的交換,也可使某個整型數的特定位的值翻轉。
  (5)按位與運算能夠用來屏蔽特定的位,也能夠用來取某個數型數中某些特定的位。
  (6)按位或運算能夠用來對某個整型數的特定位的值置l。blog

3.位運算符的優先級
 ~的優先級最高,其次是<<、>>和>>>,再次是&,而後是^,優先級最低的是|。ip


二, 按位異或運算符^

參與運算的兩個值,若是兩個相應位相同,則結果爲0,不然爲1。即:0^0=0, 1^0=1, 0^1=1, 1^1=0字符串

例如:10100001^00010001=10110000

0^0=0,0^1=1 0異或任何數=任何數

1^0=1,1^1=0 1異或任何數-任何數取反

任何數異或本身=把本身置0

(1)按位異或能夠用來使某些特定的位翻轉,如對數10100001的第2位和第3位翻轉,能夠將數與00000110進行按位異或運算。

          10100001^00000110=10100111 //1010 0001 ^ 0x06 = 1010 0001 ^ 6

(2)經過按位異或運算,能夠實現兩個值的交換,而沒必要使用臨時變量。例如交換兩個整數a,b的值,可經過下列語句實現:

    a=10100001,b=00000110

    a=a^b;   //a=10100111

    b=b^a;   //b=10100001

    a=a^b;   //a=00000110

(3)異或運算符的特色是:數a兩次異或同一個數b(a=a^b^b)仍然爲原值a.


三,Java 中除了二進制的表示方法:

因爲數據在計算機中的表示,最終以二進制的形式存在,因此有時候使用二進制,能夠更直觀地解決問題。 
  
但,二進制數太長了。好比int   類型佔用4個字節,32位。好比100,用int類型的二進制數表達將是: 
  
  0000   0000   0000   0000   0110   0100 
  
  面對這麼長的數進行思考或操做,沒有人會喜歡。所以,C,C++,以及java中   沒有提供在代碼直接寫二進制數的方法。 
  
  八進制數的表達方法 
  
  如何表達一個八進制數呢?若是這個數是   876,咱們能夠判定它不是八進制數,由於八進制數中不可能出7以上的阿拉伯數字。但若是這個數是12三、是567,或12345670,那麼它是八進制數仍是10進制數,都有可能。 
  
  因此規定,一個數若是要指明它採用八進制,必須在它前面加上一個0,如:123是十進制,但0123則表示採用八進制。這就是八進制數的表達方法。 
  
  
  如今,對於一樣一個數,好比是100,咱們在代碼中能夠用日常的10進製表達,例如在變量初始化時: 
  
  int   a   =   100; 
  
  咱們也能夠這樣寫: 
  
  int   a   =   0144;   //0144是八進制的100;一個10進制數如何轉成8進制。 
  
  千萬記住,用八進制表達時,你不能少了最前的那個0。不然計算機會統統當成10進制。不過,有一個地方使用八進制數時,卻不能使用加0,那就是咱們前面學的用於表達字符的「轉義符」表達法。 
  
  十六進制數的表達方法 
  
  若是不使用特殊的書寫形式,16進制數也會和10進制相混。隨便一個數:9876,就看不出它是16進制或10進制。 
  
  16進制數必須以   0x開頭。好比   0x1表示一個16進制數。而1則表示一個十進制。另外如:0xff,0xFF,0X102A,等等。其中的x也也不區分大小寫。(注意:0x中的0是數字0,而不是字母O) 
  
  如下是一些用法示例: 
   
  
  int   a   =   0x100F; 
  
  int   b   =   0x70   +   a; 
  
最後一點很重要,10進制數有正負之分,好比12表示正12,而-12表示負 12,;但8進制和16進制只能用達無符號的正整數,若是你在代碼中裏:-078,或者寫:-0xF2,編譯器並不把它當成一個負數。

 

 

  /* 位運算
   * java使用補碼來表示2進制數,最高位爲符號位,正數爲0,負數爲1,補碼規定:
   * 整數,最高位是0,其他是自己,如 +42的補 碼 爲 00101010
   * 負數,最高位是1,將其他的決定值按位取反,最後+1,即爲負數的補碼;
   * 如 -42的 補 碼 爲 11010110 (00101010 按位 取 反 11010101 +1=11010110 )
********
*邏輯運算*
********
   a&b 與門[真真爲真,真假爲假]
   0000 0000 0000 0000 0000 0000 0000 0001
   0000 0000 0000 0000 0000 0000 0000 0010
   =
   0000 0000 0000 0000 0000 0000 0000 0000
   System.out.println(1 & 2);
   結果爲0
   a|b 或門[假假爲假,其他全真]
   0000 0000 0000 0000 0000 0000 0000 0001
   0000 0000 0000 0000 0000 0000 0000 0010
   =
   0000 0000 0000 0000 0000 0000 0000 0011
   System.out.println(1 | 2);
   結果爲3
   ~a 非門[真則假,假則真]
      0000 0000 0000 0000 0000 0000 0000 0001
      =
      1111 1111 1111 1111 1111 1111 1111 1110
      System.out.println(~1);
      結果爲:-2
   a^b 異或門: [相同爲假,不一樣爲真]
    0000 0000 0000 0000 0000 0000 0000 0001
    0000 0000 0000 0000 0000 0000 0000 0010
    =
    0000 0000 0000 0000 0000 0000 0000 0011
    System.out.println(1^2);
    結果爲 3
********
*移位運算*
********
    a>>b 有符號右移位;將a右移b位;若正數,高位補0,負數,高位補1
   0000 0000 0000 0000 0000 0000 0000 0011
   >>1
   =
   0000 0000 0000 0000 0000 0000 0000 0001
   System.out.println(3>>1);
   結果爲1,結果與 3 / 2的1次冪相同
   a<<b 有符號左移位;將a左移b位,若正數,高位補0,負數,高位補1
   0000 0000 0000 0000 0000 0000 0000 0011
   <<2
   0000 0000 0000 0000 0000 0000 0000 1100
   System.out.println(3<<2);
   結果爲12,與3*2的2次冪相同
    a>>>b 無符號右移位;將a左移b位,不論正負,高位均補0
    0000 0000 0000 0000 0000 0000 0000 0011
   >>1
   =
   0000 0000 0000 0000 0000 0000 0000 0001
   System.out.println(3>>>1);
   結果爲1,與3/2的1次冪相同
   */
   System.out.println(3>>>1);
   System.out.println();

 

 

Java 定義的位運算(bitwise operators )直接對整數類型的位進行操做,這些整數類型包括long,int,short,char,and byte 。

運算符 結果
~ 按位非(NOT)(一元運算)
& 按位與(AND)
| 按位或(OR)
^ 按位異或(XOR)
>> 右移
>>> 右移,左邊空出的位以0填充
運算符 結果
<< 左移
& = 按位與賦值
|= 按位或賦值
^= 按位異或賦值
>> = 右移賦值
>>> = 右移賦值,左邊空出的位以0填充
<< = 左移賦值

既然位運算符在整數範圍內對位操做,所以理解這樣的操做會對一個值產生什麼效果是重要的。具體地說,知道Java 是如何存儲整數值而且如何表示負數的是有用的。所以,在繼續討論以前,讓咱們簡短概述一下這兩個話題。

全部的整數類型以二進制數字位的變化及其寬度來表示。例如,byte 型值42的二進制代碼是00101010 ,其中每一個位置在此表明2的次方,在最右邊的位以20開始。向左下一個位置將是21,或2,依次向左是22,或4,而後是8,16,32等等,依此類推。所以42在其位置1,3,5的值爲1(從右邊以0開始數);這樣42是21+23+25的和,也便是2+8+32 。

全部的整數類型(除了char 類型以外)都是有符號的整數。這意味着他們既能表示正數,又能表示負數。Java 使用你們知道的2的補碼(two’s complement )這種編碼來表示負數,也就是經過將與其對應的正數的二進制代碼取反(即將1變成0,將0變成1),而後對其結果加1。例如,-42就是經過將42的二進制代碼的各個位取反,即對00101010 取反獲得11010101 ,而後再加1,獲得11010110 ,即-42 。要對一個負數解碼,首先對其全部的位取反,而後加1。例如-42,或11010110 取反後爲00101001 ,或41,而後加1,這樣就獲得了42。

若是考慮到零的交叉(zero crossing )問題,你就容易理解Java (以及其餘絕大多數語言)這樣用2的補碼的緣由。假定byte 類型的值零用00000000 表明。它的補碼是僅僅將它的每一位取反,即生成11111111 ,它表明負零。但問題是負零在整數數學中是無效的。爲了解決負零的問題,在使用2的補碼錶明負數的值時,對其值加1。即負零11111111 加1後爲100000000 。但這樣使1位太靠左而不適合返回到byte 類型的值,所以人們規定,-0和0的表示方法同樣,-1的解碼爲11111111 。儘管咱們在這個例子使用了byte 類型的值,但一樣的基本的原則也適用於全部Java 的整數類型。

由於Java 使用2的補碼來存儲負數,而且由於Java 中的全部整數都是有符號的,這樣應用位運算符能夠容易地達到意想不到的結果。例如,無論你如何打算,Java 用高位來表明負數。爲避免這個討厭的意外,請記住無論高位的順序如何,它決定一個整數的符號。

4.2.1 位邏輯運算符
位邏輯運算符有「與」(AND)、「或」(OR)、「異或(XOR )」、「非(NOT)」,分別用「&」、「|」、「^」、「~」表示,4-3 表顯示了每一個位邏輯運算的結果。在繼續討論以前,請記住位運算符應用於每一個運算數內的每一個單獨的位。
表4-3 位邏輯運算符的結果
A 0 1 0 1 B 0 0 1 1 A | B 0 1 1 1 A & B 0 0 0 1 A ^ B 0 1 1 0 ~A 1 0 1 0

按位非(NOT)

按位非也叫作補,一元運算符NOT「~」是對其運算數的每一位取反。例如,數字42,它的二進制代碼爲:

00101010

通過按位非運算成爲

11010101

按位與(AND)

按位與運算符「&」,若是兩個運算數都是1,則結果爲1。其餘狀況下,結果均爲零。看下面的例子:

00101010 42 &00001111 15

00001010 10

按位或(OR)

按位或運算符「|」,任何一個運算數爲1,則結果爲1。以下面的例子所示:

00101010 42 | 00001111 15

00101111 47

按位異或(XOR)

按位異或運算符「^」,只有在兩個比較的位不一樣時其結果是 1。不然,結果是零。下面的例子顯示了「^」運算符的效果。這個例子也代表了XOR 運算符的一個有用的屬性。注意第二個運算數有數字1的位,42對應二進制代碼的對應位是如何被轉換的。第二個運算數有數字0的位,第一個運算數對應位的數字不變。當對某些類型進行位運算時,你將會看到這個屬性的用處。

00101010 42 ^ 00001111 15

00100101 37
位邏輯運算符的應用

下面的例子說明了位邏輯運算符:

// Demonstrate the bitwise logical operators.
class BitLogic {
public static void main(String args[]) {


String binary[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"

};
int a = 3; // 0 + 2 + 1 or 0011 in binary
int b = 6; // 4 + 2 + 0 or 0110 in binary
int c = a | b;
int d = a & b;
int e = a ^ b;
int f = (~a & b) | (a & ~b);
int g = ~a & 0x0f;


System.out.println(" a = " + binary[a]);
System.out.println(" b = " + binary);
System.out.println(" a|b = " + binary[c]);
System.out.println(" a&b = " + binary[d]);
System.out.println(" a^b = " + binary[e]);
System.out.println("~a&b|a&~b = " + binary[f]);
System.out.println(" ~a = " + binary[g]);


}
}


在本例中,變量a與b對應位的組合表明了二進制數全部的 4 種組合模式:0-0,0-1,1-0 ,和1-1 。「|」運算符和「&」運算符分別對變量a與b各個對應位的運算獲得了變量c和變量d的值。對變量e和f的賦值說明了「^」運算符的功能。字符串數組binary 表明了0到15 對應的二進制的值。在本例中,數組各元素的排列順序顯示了變量對應值的二進制代碼。數組之因此這樣構造是由於變量的值n對應的二進制代碼能夠被正確的存儲在數組對應元素binary[n] 中。例如變量a的值爲3,則它的二進制代碼對應地存儲在數組元素binary[3] 中。~a的值與數字0x0f (對應二進制爲0000 1111 )進行按位與運算的目的是減少~a的值,保證變量g的結果小於16。所以該程序的運行結果能夠用數組binary 對應的元素來表示。該程序的輸出以下:

a = 0011 b = 0110 a|b = 0111 a&b = 0010 a^b = 0101 ~a&b|a&~b = 0101 ~a = 1100

4.2.2 左移運算符
左移運算符<<使指定值的全部位都左移規定的次數。它的通用格式以下所示:

value << num
這裏,num 指定要移位值value 移動的位數。也就是,左移運算符<<使指定值的全部位都左移num位。每左移一個位,高階位都被移出(而且丟棄),並用0填充右邊。這意味着當左移的運算數是int 類型時,每移動1位它的第31位就要被移出而且丟棄;當左移的運算數是long 類型時,每移動1位它的第63位就要被移出而且丟棄。

在對byte 和short類型的值進行移位運算時,你必須當心。由於你知道Java 在對錶達式求值時,將自動把這些類型擴大爲 int 型,並且,表達式的值也是int 型。對byte 和short類型的值進行移位運算的結果是int 型,並且若是左移不超過31位,原來對應各位的值也不會丟棄。可是,若是你對一個負的byte 或者short類型的值進行移位運算,它被擴大爲int 型後,它的符號也被擴展。這樣,整數值結果的高位就會被1填充。所以,爲了獲得正確的結果,你就要捨棄獲得結果的高位。這樣作的最簡單辦法是將結果轉換爲 byte 型。下面的程序說明了這一點:

// Left shifting a byte value.
class ByteShift {


public static void main(String args[]) {
byte a = 64, b;
int i;


i = a << 2;
b = (byte) (a << 2);


System.out.println("Original value of a: " + a);
System.out.println("i and b: " + i + " " + b);
}
}


該程序產生的輸出下所示:

Original value of a: 64
i and b: 256 0


因變量a在賦值表達式中,故被擴大爲int 型,64(0100 0000 )被左移兩次生成值256 (10000 0000 )被賦給變量i。然而,通過左移後,變量b中唯一的1被移出,低位所有成了0,所以b的值也變成了0。

既然每次左移均可以使原來的操做數翻倍,程序員們常用這個辦法來進行快速的2 的乘法。可是你要當心,若是你將1移進高階位(31或63位),那麼該值將變爲負值。下面的程序說明了這一點:

// Left shifting as a quick way to multiply by 2.
class MultByTwo {


public static void main(String args[]) {
int i;
int num = 0xFFFFFFE;


for(i=0; i<4; i++) {
num = num << 1;
System.out.println(num);


}
}
這裏,num 指定要移位值value 移動的位數。也就是,左移運算符<<使指定值的全部位都左移num位。每左移一個位,高階位都被移出(而且丟棄),並用0填充右邊。這意味着當左移的運算數是int 類型時,每移動1位它的第31位就要被移出而且丟棄;當左移的運算數是long 類型時,每移動1位它的第63位就要被移出而且丟棄。

在對byte 和short類型的值進行移位運算時,你必須當心。由於你知道Java 在對錶達式求值時,將自動把這些類型擴大爲 int 型,並且,表達式的值也是int 型。對byte 和short類型的值進行移位運算的結果是int 型,並且若是左移不超過31位,原來對應各位的值也不會丟棄。可是,若是你對一個負的byte 或者short類型的值進行移位運算,它被擴大爲int 型後,它的符號也被擴展。這樣,整數值結果的高位就會被1填充。所以,爲了獲得正確的結果,你就要捨棄獲得結果的高位。這樣作的最簡單辦法是將結果轉換爲 byte 型。下面的程序說明了這一點:

// Left shifting a byte value.
class ByteShift {


public static void main(String args[]) {
byte a = 64, b;
int i;


i = a << 2;
b = (byte) (a << 2);


System.out.println("Original value of a: " + a);
System.out.println("i and b: " + i + " " + b);
}
}


該程序產生的輸出下所示:

Original value of a: 64
i and b: 256 0


因變量a在賦值表達式中,故被擴大爲int 型,64(0100 0000 )被左移兩次生成值256 (10000 0000 )被賦給變量i。然而,通過左移後,變量b中唯一的1被移出,低位所有成了0,所以b的值也變成了0。

既然每次左移均可以使原來的操做數翻倍,程序員們常用這個辦法來進行快速的2 的乘法。可是你要當心,若是你將1移進高階位(31或63位),那麼該值將變爲負值。下面的程序說明了這一點:

// Left shifting as a quick way to multiply by 2.
class MultByTwo {


public static void main(String args[]) {
int i;
int num = 0xFFFFFFE;


for(i=0; i<4; i++) {
num = num << 1;
System.out.println(num);


}
}
}

該程序的輸出以下所示:

536870908
1073741816
2147483632
-32


初值通過仔細選擇,以便在左移 4 位後,它會產生-32。正如你看到的,當1被移進31 位時,數字被解釋爲負值。

4.2.3 右移運算符
右移運算符>>使指定值的全部位都右移規定的次數。它的通用格式以下所示:

value >> num

這裏,num 指定要移位值value 移動的位數。也就是,右移運算符>>使指定值的全部位都右移num位。下面的程序片斷將值32右移2次,將結果8賦給變量a:

int a = 32;
a = a >> 2; // a now contains 8


當值中的某些位被「移出」時,這些位的值將丟棄。例如,下面的程序片斷將35右移2 次,它的2個低位被移出丟棄,也將結果8賦給變量a:

int a = 35;
a = a >> 2; // a still contains 8


用二進制表示該過程能夠更清楚地看到程序的運行過程:

00100011 35
>> 2
00001000 8


將值每右移一次,就至關於將該值除以2而且捨棄了餘數。你能夠利用這個特色將一個整數進行快速的2的除法。固然,你必定要確保你不會將該數原有的任何一位移出。

右移時,被移走的最高位(最左邊的位)由原來最高位的數字補充。例如,若是要移走的值爲負數,每一次右移都在左邊補1,若是要移走的值爲正數,每一次右移都在左邊補0,這叫作符號位擴展(保留符號位)(sign extension ),在進行右移操做時用來保持負數的符號。例如,–8 >> 1 是–4,用二進制表示以下:

11111000 –8 >>1 11111100 –4

一個要注意的有趣問題是,因爲符號位擴展(保留符號位)每次都會在高位補1,所以-1右移的結果老是–1。有時你不但願在右移時保留符號。例如,下面的例子將一個byte 型的值轉換爲用十六
進製表示。注意右移後的值與0x0f進行按位與運算,這樣能夠捨棄任何的符號位擴展,以便獲得的值能夠做爲定義數組的下標,從而獲得對應數組元素表明的十六進制字符。

// Masking sign extension.
class HexByte {
static public void main(String args[]) {


char hex[] = {
’0’, ’1’, ’2’, ’3’, ’4’, ’5’, ’6’, ’7’,
’8’, ’9’, ’a’, ’b’, ’c’, ’d’, ’e’, ’f’’


};
byte b = (byte) 0xf1;


System.out.println("b = 0x" + hex[(b >> 4) & 0x0f] + hex[b & 0x0f]);}}

該程序的輸出以下:

b = 0xf1

4.2.4 無符號右移
正如上面剛剛看到的,每一次右移,>>運算符老是自動地用它的先前最高位的內容補它的最高位。這樣作保留了原值的符號。但有時這並非咱們想要的。例如,若是你進行移位操做的運算數不是數字值,你就不但願進行符號位擴展(保留符號位)。當你處理像素值或圖形時,這種狀況是至關廣泛的。在這種狀況下,無論運算數的初值是什麼,你但願移位後老是在高位(最左邊)補0。這就是人們所說的無符號移動(unsigned shift )。這時你可使用Java 的無符號右移運算符>>> ,它老是在左邊補0。

下面的程序段說明了無符號右移運算符>>> 。在本例中,變量a被賦值爲-1,用二進制表示就是32位全是1。這個值而後被無符號右移24位,固然它忽略了符號位擴展,在它的左邊老是補0。這樣獲得的值255被賦給變量a。

int a = -1; a = a >>> 24;

下面用二進制形式進一步說明該操做:

11111111 11111111 11111111 11111111 int型-1的二進制代碼>>> 24 無符號右移24位00000000 00000000 00000000 11111111 int型255的二進制代碼

因爲無符號右移運算符>>> 只是對32位和64位的值有意義,因此它並不像你想象的那樣有用。由於你要記住,在表達式中太小的值老是被自動擴大爲int 型。這意味着符號位擴展和移動老是發生在32位而不是8位或16位。這樣,對第7位以0開始的byte 型的值進行無符號移動是不可能的,由於在實際移動運算時,是對擴大後的32位值進行操做。下面的例子說明了這一點:

// Unsigned shifting a byte value.
class ByteUShift {
static public void main(String args[]) {
進製表示。注意右移後的值與0x0f進行按位與運算,這樣能夠捨棄任何的符號位擴展,以便獲得的值能夠做爲定義數組的下標,從而獲得對應數組元素表明的十六進制字符。

// Masking sign extension.
class HexByte {
static public void main(String args[]) {


char hex[] = {
’0’, ’1’, ’2’, ’3’, ’4’, ’5’, ’6’, ’7’,
’8’, ’9’, ’a’, ’b’, ’c’, ’d’, ’e’, ’f’’


};
byte b = (byte) 0xf1;


System.out.println("b = 0x" + hex[(b >> 4) & 0x0f] + hex[b & 0x0f]);}}

該程序的輸出以下:

b = 0xf1

4.2.4 無符號右移
正如上面剛剛看到的,每一次右移,>>運算符老是自動地用它的先前最高位的內容補它的最高位。這樣作保留了原值的符號。但有時這並非咱們想要的。例如,若是你進行移位操做的運算數不是數字值,你就不但願進行符號位擴展(保留符號位)。當你處理像素值或圖形時,這種狀況是至關廣泛的。在這種狀況下,無論運算數的初值是什麼,你但願移位後老是在高位(最左邊)補0。這就是人們所說的無符號移動(unsigned shift )。這時你可使用Java 的無符號右移運算符>>> ,它老是在左邊補0。

下面的程序段說明了無符號右移運算符>>> 。在本例中,變量a被賦值爲-1,用二進制表示就是32位全是1。這個值而後被無符號右移24位,固然它忽略了符號位擴展,在它的左邊老是補0。這樣獲得的值255被賦給變量a。

int a = -1; a = a >>> 24;

下面用二進制形式進一步說明該操做:

11111111 11111111 11111111 11111111 int型-1的二進制代碼>>> 24 無符號右移24位00000000 00000000 00000000 11111111 int型255的二進制代碼

因爲無符號右移運算符>>> 只是對32位和64位的值有意義,因此它並不像你想象的那樣有用。由於你要記住,在表達式中太小的值老是被自動擴大爲int 型。這意味着符號位擴展和移動老是發生在32位而不是8位或16位。這樣,對第7位以0開始的byte 型的值進行無符號移動是不可能的,由於在實際移動運算時,是對擴大後的32位值進行操做。下面的例子說明了這一點:

// Unsigned shifting a byte value.
class ByteUShift {
static public void main(String args[]) {
int b = 2;
int c = 3;


a |= 4;
b >>= 1;
c <<= 1;
a ^= c;
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("c = " + c);


}
}


該程序的輸出以下所示:

a = 3
b = 1
c = 6
出處:http://blog.csdn.net/dingxy/archive/2009/04/30/4140149.aspx

相關文章
相關標籤/搜索