一、什么是位运算符

位运算符主要针对二进制的运算,就像加减乘除适用与十进制,而位运算符就是针对两个二进制数的位进行逻辑运算

二、位运算符有哪些

操作符

说明

&


|


~

取反

^

异或

>>

右移

<<

左移

>>>

无符号右移

三、各个位运算符的详解

3.1 与运算符(&)

与运算符用符号“&”表示:
运算规则:两个操作数中的 位 都为1,结果才为1,否则结果为0,例如下面的程序段。

package com.leely;

public class Test {
    public static void main(String[] args) {
        byte a = 11;  // 二进制为 00001011
        byte b = 22; // 二进制为  00010110
        System.out.println("位运算符 a&b 的结果为:"+(a&b));

        //都为1 才为 1
        //(a&b) 的结果为 :  00000010 转换为10进制等于 2

        //位运算符 a&b 的结果为:2
    }
}

3.2 或运算符(|)

或运算符用符号 | 表示 :

运算规则:两个操作数中的 位 如果相对应位都是 0,则结果为 0,否则为 1,例如下面的程序段。

package com.leely;

public class Test {
    public static void main(String[] args) {
        byte a = 11;  // 二进制为 00001011
        byte b = 22; // 二进制为  00010110
        System.out.println("位运算符 a|b 的结果为:"+(a|b));

        //全 0 才为 0 
        //(a|b) 的结果为 :  00011111 转换为十进制等于 31


        //位运算符 a|b 的结果为:31
    }
}

**注意点 : 在或运算符中 全1 也为 1 **

3.3 取反运算符(~)

取反运算符用符号 ~ 表示 :

运算规则:操作数中的位,如果 为 0 则取反为1 如果为 1 则取反为 0 ,例如下面的程序段。

package com.leely;

public class Test {
    public static void main(String[] args) {
        byte a = 11;  // 二进制为 00001011
        byte b = 22; // 二进制为  00010110
        System.out.println("位运算符 ~a 的结果为:"+(~a));
        System.out.println("位运算符 ~b 的结果为:"+(~b));

        // 0 为 1 , 1 为 0
        // 0 为 1 , 1 为 0
        //(~a) 的结果为 :  11110100 转换为十进制等于 -12
        //(~b) 的结果为 :  11101001 转换为十进制等于 -23


        //位运算符 ~a 的结果为:-12
        //位运算符 ~b 的结果为:-23
    }
}

为什么11110100转换为十进制等于 -12,11101001 转换为十进制等与-23 ,这就要从二进制的存储方式讲起。计算机并不直接存储二进制原码,而是存储二进制的补码,正数的补码就是原码,负数的补码,是“符号位不变,原码取反码再加一”,负数输出时,将补码逆向译成原码

这样去解释会比较绕 ,我们先了解下什么是原码, 反码和补码。

3.3.1 原码

原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:

[+1]原 = 0000 0001

[-1]原 = 1000 0001

第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:

[1111 1111 , 0111 1111]

[-127 , 127]

原码是人脑最容易理解和计算的表示方式.

3.3.2 反码

反码的表示方法是:

正数的反码是其本身

负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.

[+1] = [00000001]原 = [00000001]反 
[-1] = [10000001]原 = [11111110]反

可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计算.

3.3.3 补码

补码的表示方法是:

正数的补码就是其本身

负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

[+1] = [00000001]原 = [00000001]反 = [00000001]补

[-1] = [10000001]原 = [11111110]反 = [11111111]补

对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.

由此我们可以了解 11110100 在计算机看来就是负数的补码 ,在输出的时候,计算机对其进行转换

11110100  补码 
转换为反码:
  减 1:
  11110011 
转换为原码:
  取反:
  10001100
  
  结果为 : -12

3.4 异或运算符 (^)

异或运算符用符号“^”表示

运算规则:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位相同(同时为 0 或同时为 1)时,结果为 0;如果对应的二进制位不相同,结果则为 1。

package com.leely;

public class Test {
    public static void main(String[] args) {
        int a = 10;
        int b = 12;
        System.out.println("a的二进制值为:"+ Integer.toBinaryString(a));
        System.out.println("b的二进制值为:"+ Integer.toBinaryString(b));
        System.out.println("a^b 的值为:"+ Integer.toBinaryString(a^b));
      
        //结果
//        a的二进制值为:1010
//        b的二进制值为:1100
//        a^b 的值为:  0110
    }
}

3.5 右位移运算符(>>)

右移运算符用符号 ”>>“表示

运算规则:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),如果该数为正数则高位的空位补零,如果为负数,则高位补1。

package com.leely;

public class Test {
    public static void main(String[] args) {
        int a = 10;
        int b = -10;
        System.out.println("a的二进制值为:"+ Integer.toBinaryString(a));
        System.out.println("a>>2 的值为:"+ Integer.toBinaryString(a>>2));
        System.out.println("b的二进制值为:"+ Integer.toBinaryString(b));
        System.out.println("b>>2 的值为:"+ Integer.toBinaryString(b>>2));
        //结果
//        a的二进制值为:00001010 
//        a>>2 的值为: 00000010
//        b的二进制值为:11111111111111111111111111110110
//        b>>2 的值为: 11111111111111111111111111111101
    }
}

3.6 左位移运算符 (<<)

左位移运算符用符号“<<”表示

运算规则: 按二进制形式把所有的数字向左移动对应的位数, 高位移出(舍弃),正负数一样,低位的空位补零

package com.leely;

public class Test {
    public static void main(String[] args) {
        int a = 10;
        int b = -10;
        System.out.println("a的二进制值为:"+ Integer.toBinaryString(a));
        System.out.println("a<<2 的值为:"+ Integer.toBinaryString(a<<2));
        System.out.println("b的二进制值为:"+ Integer.toBinaryString(b));
        System.out.println("b<<2 的值为:"+ Integer.toBinaryString(b<<2));
        //结果
//        a的二进制值为:1010
//        a<<2 的值为:101000
//        b的二进制值为:11111111111111111111111111110110
//        b<<2 的值为:11111111111111111111111111011000

    }
}

3.7 无符号右位移符 (>>>)

无符号右位移符用 符号“>>>”表示

运算规则:表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0

package com.leely;

public class Test {
    public static void main(String[] args) {
        int a = 10;
        int b = -10;
        System.out.println("a的二进制值为:"+ Integer.toBinaryString(a));
        System.out.println("a>>>2 的值为:"+ Integer.toBinaryString(a>>>2));
        System.out.println("b的二进制值为:"+ Integer.toBinaryString(b));
        System.out.println("b>>>2 的值为:"+ Integer.toBinaryString(b>>>3));
        //结果
//        a的二进制值为:1010
//        a>>>2 的值为:0010
//        b的二进制值为:11111111111111111111111111110110
//        b>>>2 的值为:00011111111111111111111111111110

    }
}

四、复合位赋值运算符

所有的二进制位运算符都有一种将赋值位运算 组合在一起的简写形式。复合位赋值运算符由赋值运算符位运算符组合而成。下表列出了组合后的复合位赋值运算符。

复合位赋值运算符

运算符

含义

实例

结果

&=

按位与赋值

num1 &= num2

等价于 num 1=num 1 & num2

`

=`

按位或赋值

num1 |= num2

^=

按位异或赋值

num1 ^= num2

等价于 num 1=num 1 ^ num2

«=

按位左移赋值

num1 «= num2

等价于 num 1=num 1 « num2

»=

按位右移赋值

num1 »= num2

等价于 num 1=num 1 » num2