目录

裴先生
裴先生
发布于 2021-01-03 / 4 阅读
0
0

Java 按位与移位操作符详解

原创

1. 按位操作符(Bitwise Operators)

定义

按位操作符用于操作整数基本类型中的单个“比特”(bit),即二进制位。它们会对两个参数中对应的位执行布尔代数运算,并最终生成一个结果。

背景:按位操作符来源于 C 语言面向底层的操作,在这种操作中经常需要直接操纵硬件、设置硬件寄存器内的二进制位。不过在当前的 Java 开发过程中并不会过多用到位运算,仅供了解。

运算原理

操作符名称运算规则
&按位与两个输入位都是 1,则输出 1;否则输出 0
``按位或
^按位异或两个输入位相同(都是 0 或都是 1)则输出 0;不同时输出 1
~按位非(取反)生成与输入位相反的值(0→1,1→0)

操作符特性

  • 一元 vs 二元~ 是一元操作符,只能对一个操作数进行操作;其他按位操作符是二元操作符
  • 复合赋值&=|=^= 都是合法的
  • 限制:由于 ~ 是一元操作符,所以不可与 = 联合使用

布尔类型支持

  • 可执行按位 &|^ 运算
  • 不能执行按位 ~(为了避免与逻辑 NOT 混淆)

示例代码

public class BitwiseOperators {
    public static void main(String[] args) {
        int i = 666;
        System.out.println(Integer.toBinaryString(i)); // 1010011010
        int j = 777;
        System.out.println(Integer.toBinaryString(j)); // 1100001001
        
        System.out.println("===========按位运算符=============");
        // 按位与 &
        System.out.println("按位与&   :" + Integer.toBinaryString(i & j)); // 1000001000
        // 按位或 |
        System.out.println("按位或|   :" + Integer.toBinaryString(i | j)); // 1110011011
        // 按位异或 ^
        System.out.println("按位异或^ :" + Integer.toBinaryString(i ^ j)); // 110010011
        System.out.println("===========按位运算符=============");
    }
}

2. 移位操作符(Shift Operators)

定义

移位操作符操作的运算对象也是二进制的“位”,并且只可以用来处理整数类型(基本类型的一种)。

运算原理

操作符名称运算规则
<<左移位按右侧指定的位数将左侧操作数向左移动,在低位补 0
>>有符号右移按右侧指定的位数将左侧操作数向右移动,使用“符号扩展”(正数高位补 0,负数高位补 1)
>>>无符号右移按右侧指定的位数将左侧操作数向右移动,使用“零扩展”(无论正负,高位都补 0)

注意>>> 操作符在 C 或 C++ 中没有,是 Java 特有的。

类型转换规则

charbyteshort 类型:

  • 移位前会先被转换成 int 类型
  • 结果也是 int 类型的值
  • 只有数值右端的低 5 位才有用(因为 2⁵ = 32,而 int 型只有 32 位)

long 类型:

  • 结果也是 long 类型
  • 只有数值右端的低 6 位才有用(因为 2⁶ = 64,而 long 型有 64 位)

复合赋值与注意事项

  • 合法操作<<=>>=>>>= 都是合法的
  • 潜在问题:对 byteshort 值使用 >>>= 时,可能得到不正确的结果:
    • 先转成 int 类型
    • 进行右移操作
    • 然后被截断并赋值给原来的类型
    • 在这种情况下可能得到 -1 的结果

示例代码

public class ShiftOperators {
    public static void main(String[] args) {
        // int 类型
        int i = -1;
        System.out.println("int i 移位运算符 :" + Integer.toBinaryString(i));
        i >>>= 10;
        System.out.println("int i 移位运算符 :" + Integer.toBinaryString(i));
        
        System.out.println("=============================");
        
        // long 类型
        long j = -1;
        System.out.println("long j 移位运算符 :" + Long.toBinaryString(j));
        j >>>= 10;
        System.out.println("long j 移位运算符 :" + Long.toBinaryString(j));
        
        System.out.println("=============================");
        
        // short 类型(注意结果)
        short s = -1;
        System.out.println("short s 移位运算符 :" + Integer.toBinaryString(s));
        s >>>= 10;
        System.out.println("short s 移位运算符 :" + Integer.toBinaryString(s));
        
        System.out.println("=============================");
        
        // byte 类型(注意结果)
        byte b = -1;
        System.out.println("byte b 移位运算符 :" + Integer.toBinaryString(b));
        b >>>= 10;
        System.out.println("byte b 移位运算符 :" + Integer.toBinaryString(b));
    }
}

输出结果说明

  • intlong 类型的无符号右移能正确显示结果
  • shortbyte 类型由于类型转换和截断,结果显示为全 1(即 -1)

原创

版权声明:本博客原创文章,由 裴先生 2021年01月03日 发表。
转载说明:除特殊说明外本站文章皆由 CC BY-NC-SA 4.0 协议发布,转载须注明出处。


评论