1. 程式人生 > >【Java】位操作符

【Java】位操作符

# 位運算子 java支援的位運算子有7個,分為兩類:位邏輯運算和移位運算。位邏輯運算子包括按位取反(~)、按位與(&)、按位或(|)和按位異或(^)4種,。移位運算子包括左移(<<)、右移(>>)和無符號右移(>>>)3種。位運算子只能用於整型資料,包括byte、short、int、long和char型別。下表列出了各種位運算子的功能與示例。假設a = 10, b = 3。 ~運算子是對運算數的每一位按位取反。 下表列出了位運算子的基本運算,假設整數變數A的值為60和變數B的值為13: |操作符 |描述 |例子| |---|---|---| |`&`| 如果相對應位都是1,則結果為1,否則為0 |`A & B`得到12,即0000 1100| |`|`|如果相對應位都是0,則結果為0,否則為1 |`A | B`得到61,即 0011 1101| |`^`|如果相對應位值相同,則結果為0,否則為1 |`A ^ B`得到49,即 0011 0001| |`~`|按位取反運算子翻轉運算元的每一位,即0變成1,1變成0。 |`~A`得到-61,即1100 0011| |`<<`|按位左移運算子。左運算元按位左移右運算元指定的位數。
(低位補零) |`A << 2`得到240,即 1111 0000| |`>>`|“有符號”按位右移運算子。左運算元按位右移右運算元指定的位數。
該操作符使用 “符號擴充套件”:若符號為正,則高位插入 0;若符號為負,則高位插入 1。 |`A >> 2`得到15即 1111| |`>>>`|“無符號”按位右移補零操作符。左運算元的值按右運算元指定的位數右移,移動得到的空位以零填充。
該操作符使用 “零擴充套件”,無論正負,都在高位插入 0。|`A>>>2`得到15即0000 1111| # 按位操作符 按位操作符用來操作整數的二進位制位,會對兩個引數中對應的位執行布林代數運算,並最終生成一個結果。 與操作符 “&”,如果兩個輸入位都是 1,那麼輸出位是 1,否則輸入位是 0; 或操作符 “|” ,如果兩個輸入位有一個是 1,那麼輸出位是 1,只有兩個輸入位都是 0,輸出位才是 0; 異或運算子 “^”,如果兩個輸入位都為 1 或者都為 0,那麼輸出位是 0,否則輸出位是 1。 非運算子 “~”,這個一元操作符,只能對一個數操作,規則是輸出位與輸入位相反。 ``` //轉化為二進位制:0101 int num1 = 5; //轉化為二進位制:1001 int num2 = 9; //與運算,二進位制結果為 0001,列印結果為 1 System.out.println(num1 & num2); //或運算,二進位制結果為 1101,列印結果為 13 System.out.println(num1 | num2); //異或運算,二進位制結果為 1100,列印結果為 12 System.out.println(num1 ^ num2); //非運算,二進位制結果為 11111111111111111111111111111010,列印結果 -6 System.out.println(Integer.toBinaryString(~num1)); ``` 好吧,進哥承認,我看到那個 -6 也蒙了那麼一下,所以整理了以下內容。 ## 補充 數字的二進位制表現形式為 “有符號的二進位制補碼”。 原碼:數字的二進位制表示法,最高位為符號位, “ 0 ” 為正,“ 1 ” 為負。 反碼:正數的反碼與原碼相同,負數的反碼對原碼逐位取反,符號位除外。 補碼:正數的補碼與原碼相同,負數的補碼在其反碼末位加 1。 負數的二進位制演算法(以 -6 為例): 1)將 -6 的絕對值轉化為二進位制,即:00000000 00000000 00000000 00000110 2)求該二進位制數的反碼,即:11111111 11111111 11111111 11111001 3)對以上求得的二進位制數加 1,即:11111111 11111111 11111111 11111010 # 移位操作符 移位操作符的運算物件也是二進位制的 “位”,但是隻能用來處理整數型別。 - 左移位操作符 “<<” 按照操作符右側指定的位數將操作符左邊的運算元向左移動(低位補零); - “有符號”右移位操作符 “>>” 按照操作符右側指定的位數將操作符左邊的運算元向右移動。該操作符使用 “符號擴充套件”:若符號為正,則高位插入 0;若符號為負,則高位插入 1。 - “無符號”右移位操作符 “>>>”,該操作符使用 “零擴充套件”,無論正負,都在高位插入 0。 ``` //二進位制 1111; int i = 15; //向右邊移動兩位,二進位制結果為 0011,列印結果為 3 System.out.println(i >> 2); //向左邊移動兩位,二進位制結果為 111100,列印結果為 60 System.out.println(i << 2); ``` 移位操作符可以與等號組合使用(<<= 或 >>= 或 >>>=),表示操作符左邊的值會移動由右邊數值指定的位數,再將得到的結果賦給左邊的變數。 --- # Java運算子 Java運算子按功能可分為:算數運算子、關係運算符、邏輯運算子、位運算子、賦值運算子和條件運算子。 ## 算數運算子 算術運算子包括通常的加(+)、減(-)、乘(*)、除(/)、取模(%),完成整數型和浮點型資料的算術運算。 > 許多語言中的取模運算只能用於整數型,Java對此做了擴充套件,它允許對浮點數進行取模操作。例如,3%2 的結果是 1, 15.2%5 的結果是 0.2。取模操作還可以用於負數,結果的符號與第一個運算元的符號相同,例如,5%-3 的結果是 2,-5%3 的結果是-2。 此外,算術運算子還有“++”和“--”兩種,分別稱為加1和減1運算子。這兩種運算子有字首形式和字尾形式,含有有所不同。例如,i++ 和 ++i 的執行順序是不一樣的,i++ 在 i 使用之後再 +1,++i 在 i 使用之前先 +1。i-- 和 --i 的情況於此類似。 例子: ``` int i = 1; System.out.println(i++); //i++,使用之後+1,此處輸出1 int i = 1; System.out.println(++i); //++i,先+1再使用,此處輸出2 int i = 1; System.out.println(i--); //i--,使用之後-1,此處輸出1 int i = 1; System.out.println(--i); //--i,先-1再使用,此處輸出0 ``` ## 關係運算符 關係運算符用來比較兩個值,包括大於(>)、小於(<)、大於等於(>=)、小於等於(<=)、等於(==)和不等於(!=)6種。關係運算符都是二元運算子,也就是每個運算子都帶有兩個運算元,運算的結果是一個邏輯值。Java允許“==”和“!=”兩種運算子用於任何資料型別。例如,既可以判斷兩個數的值是否相等,也可以判斷物件或陣列的例項是否相等。判斷例項時比較的是兩個物件在記憶體中的引用地址是否相等。 ## 邏輯運算子 邏輯運算子包括邏輯與(&&)、邏輯或(||)和邏輯非(!)。前兩個是二元運算子,後一個是一元運算子。Java對邏輯與和邏輯或提供“短路”功能,也就是在進行運算時,先計算運算子左側的表示式的值,如果使用該值能得到整個表示式的值,則跳過運算子右側表示式的計算,否則計算運算子右側表示式,並得到整個表示式的值。 ``` //邏輯與&&,有一個表示式的結果是false,整體就返回false String str = null; if(str != null && str.length0 >
2) { // str是null, &&左側的表示式的結果是false,不會計算&&右側的表示式,直接整體返回false } str= "abc"; if(str != null && str.length0> 5) { // &&左側的表示式的結果是true,會接著計算&&右側的表示式,右側表示式的值是false,整個if中的表示式的結果就返回false } //邏輯或||,有一個表示式的結果是true,整體就返回true str= "qq"; if(str == null II str.length0== 2) { // ||左側的表示式的結果是false,會接著計算||右側的表示式,右側結果是true, 則整體返回true } if(str != null II str.ength0 == 2) { // ||左側的表示式的結果是true, 不會計算||右側的表示式, 直接整體返回true } //邏輯非!,表示式結果是true,就返回false; 表示式結果是false,就返回true boolean flag = true; System.out.printIn(!flag); //輸出false flag = false; System.out.printn(!flag); //輸出true ``` ## 位運算子 位運算子用來對二進位制位進行操作,包括按位取反(~)、按位與(&)、按位或(|)、異或(^)、右移(>
>)、左移(<<)和無符號右移(>>>)。位運算子只能對整數型和字元型資料進行操作。 ### 1. 取反(~) 參加運算的一個數據,按二進位制位進行“取反”運算。 運算規則:~1=0; ~0=1; 即:對一個二進位制數按位取反,即將0變1,1變0。 ### 2. 按位與(&) 參加運算的兩個資料,按二進位制位進行“與”運算。 運算規則:0&0=0; 0&1=0; 1&0=0; 1&1=1;即:兩位同時為“1,結果才為“1,否則為0。 例如:3&5 即 0000 0011 & 0000 0101 = 0000 0001 因此,3 & 5的值得1。 ### 3. 按位或(|) 參加運算的兩個物件,按二進位制位進行“或”運算。 運算規則:0 | 0=0; 0 | 1=1; 1 | 0=1; 1 | 1=1; 即 :參加運算的兩個物件只要有一個為1,其值為1。 例如:3 | 5,即 0000 0011 | 0000 0101 = 0000 0111 因此,3 | 5的值得7。 ### 4. 異或(^) 參加運算的兩個資料,按二進位制位進行“異或”運算。 運算規則:0^0=0; 0^1=1; 1^0=1; 1^1=0; 即:參加運算的兩個物件,如果兩個相應位為“異”(值不同),則該位結果為1,否則為0。 ### 5. 左移(<<) 運算規則:按二進位制形式把所有的數字向左移動對應的位數,高位移出(捨棄),低位的空位補零。例如: 12345 << 1,則是將數字12345左移1位: ![](https://img2020.cnblogs.com/blog/1542615/202101/1542615-20210117164217426-1889164234.png) 位移後十進位制數值變成:24690,剛好是12345的二倍,所以有些人會用左位移運算子代替乘2的操作,但是這並不代表是真的就是乘以2,很多時候,我們可以這樣使用,但是一定要知道,位移運算子很多時候可以代替乘2操作,但是這個並不代表兩者是一樣的。 思考一下:如果任意一個十進位制的數左位移32位,右邊補位32個0,十進位制豈不是都是0了?當然不是!!! 當int 型別的資料進行左移的時候,當左移的位數大於等於32位的時候,位數會先求餘數,然後再進行左移,也就是說,如果真的左移32位 12345 << 32 的時候,會先進行位數求餘數,即為 12345<<(32%32) 相當於 12345<< 0 ,所以12345<< 33 的值和12345<<1 是一樣的,都是 24690。 ### 6. 右移(>>) 同樣,還是以12345這個數值為例,12345右移1位: 12345>>1。 ![](https://img2020.cnblogs.com/blog/1542615/202101/1542615-20210117164222086-2128481806.png) 右移後得到的值為 6172 和int 型別的資料12345除以2取整所得的值一樣,所以有些時候也會被用來替代除2操作。另外,對於超過32位的位移,和左移運算子一樣,,會先進行位數求餘數。 ### 7. 無符號右移(>>>) 無符號右移運算子和右移運算子是一樣的,不過無符號右移運算子在右移的時候是補0的,而右移運算子是補符號位的。以下是-12345二進位制表示: ![](https://img2020.cnblogs.com/blog/1542615/202101/1542615-20210117164231931-746865151.png) 對於原始碼、反碼、補碼不熟悉的同學,請自行學習,這裡就不再進行補充了講解了,這裡提醒一下,在右移運算子中,右移後補0,是由於正數 12345 符號位為0 ,如果為1,則應補1。 ![](https://img2020.cnblogs.com/blog/1542615/202101/1542615-20210117164236763-1292281200.png) > 1、原碼、反碼和補碼說明:一個數可以分成符號位(0正1負)+ 真值,原碼是我們正常想法寫出來的二進位制。由於計算機只能做加法,負數用單純的二進位制原碼書寫會出錯,於是大家發明了反碼(正數不變,負數符號位不變,真值部分取反);再後來由於+0, -0的爭端,於是改進反碼,變成補碼(正數不變,負數符號位不變,真值部分取反,然後+1)。二進位制前面的0都可以省略,所以總結來說:計算機裡的負數都是用補碼(符號位1,真值部分取反+1)表示的。2、位運算子和2的關係位運算子和乘2、除2在大多數時候是很相似的,可以進行替代,同時效率也會高的多,但是兩者切記不能混淆 ;很多時候有人會把兩者的概念混淆,尤其是資料剛好是 2、4、6、8、100等偶數的時候,看起來就更相似了,但是對於奇數,如本文使用的12345 ,右移之後結果為6172 ,這個結果就和數學意義上的除以2不同了,不過對於int 型別的資料,除2 會對結果進行取整,所以結果也是6172 ,這就更有迷惑性了。 ## 賦值運算子 賦值運算子的作用就是將常量、變數或表示式的值賦給某一個變數。 |運算子|運算|範例|結果| |---|---|---|---| |`=`|賦值|a=3;b=2;|a=3;b=2;| |`+=`|加等於|a=3;b=2;a+=b;|a=5;b=2;| |`-=`|減等於|a=3;b=2;a-=b;|a=1;b=2;| |`*=`|乘等於|a=3;b=2;a*=b;|a=6;b=2;| |`/=`|除等於|a=3;b=2;a/=b;|a=1;b=2;| |`%=`|模等於|a=3;b=2;a%=b;|a=3;b=2;| 除了“=”,其它的都是特殊的賦值運算子,以“+=”為例,x += 3就相當於x = x + 3,首先會進行加法運算x+3,再將運算結果賦值給變數x。-=、*=、/=、%=賦值運算子都可依此類推。 ## 條件運算子 條件運算子( ? : )也稱為 “三元運算子”或“三目運算子”。 語法形式:布林表示式 ? 表示式1 :表示式2。 運算過程:如果布林表示式的值為 true ,則返回 表示式1的值,否則返回 表示式2 的值。 ## 運算子的優先次序 在對一個表示式進行計算時,如果表示式中含有多種運算子,則要安運算子的優先次序一次從高向低進行。運算子的優先次序如下: ![](https://img2020.cnblogs.com/blog/1542615/202101/1542615-20210117164913888-521540700.png) |優先順序|運算子 |簡介 |結合性| |----|----|----|----| |1 |[]、.、() |方法呼叫,屬性獲取 |從左向右| |2 |!、~、++、-- |一元運算子 |從右向左| |3 |*、/、% |乘、除、取模(餘數) |從左向右| |4 |+、- |加、減 |從左向右| |5 |<<、>>、>>> |左位移、右位移、無符號右位移 |從左向右| |6 |<、<=、>、>=、instanceof |小於、小於等於、大於、大於等於
物件型別判斷是否屬於同類型 |從左向右| |7 |==、!= |相等、不相等 |從左向右| |8 |& |按位與 |從左向右| |9 |^ |按位異或 |從左向右| |10 |\| |按位或 |從左向右| |11 |&& |邏輯與 |從左向右| |12 |\|\| |邏輯或 |從左向右| |13 |? |條件運算子 |從右向左| |14 |=、+=、-=、*=、/=、%=、&=、\|=、^=、>>= |混合賦值運算子 |從右