在 Java 中,位运算符(Bitwise Operators) 允许我们直接对整数的二进制位进行操作。它们是低级编程、性能优化和特定算法(如加密、压缩、图形处理)的核心工具。虽然日常开发中不常使用,但掌握位运算能让你写出更高效、更紧凑的代码。
理解 Java 中 7 种位运算符的作用与原理
掌握按位与、或、异或、取反及三种移位操作的使用方法
能够将十进制数转换为二进制并手动计算位运算结果
了解位运算在实际场景中的应用价值
避免常见误区(如补码表示、符号位处理等)
位运算符作用于 byte、short、int、long 等整数类型的每一位,直接在二进制层面进行逻辑或算术操作。Java 提供以下 7 种位运算符:
💡 所有位运算都在 32 位(int)或 64 位(long) 的二进制补码表示下进行。
&) “全 1 才 1”只有当两个对应位都为 1 时,结果位才为 1。
int a = 5; // 二进制: 0101
int b = 7; // 二进制: 0111
// 按位与:
// 0101
// & 0111
// ------
// 0101 → 十进制 5
System.out.println(a & b); // 输出: 5应用场景
掩码(Masking):提取特定位
int flags = 0b10110010;
boolean isFeatureEnabled = (flags & 0b00000100) != 0; // 检查第 3 位判断奇偶:(n & 1) == 0 表示偶数
|)“有 1 就 1”只要有一个对应位为 1,结果位就为 1。
int a = 5; // 0101
int b = 7; // 0111
// 按位或:
// 0101
// | 0111
// ------
// 0111 → 十进制 7
System.out.println(a | b); // 输出: 7应用场景
设置标志位:
int permissions = READ;
permissions |= WRITE; // 添加写权限^) “不同为 1”对应位不同时结果为 1,相同则为 0。
int a = 5; // 0101
int b = 7; // 0111
// 按位异或:
// 0101
// ^ 0111
// ------
// 0010 → 十进制 2
System.out.println(a ^ b); // 输出: 2特性与应用
自反性:a ^ a = 0
交换律 / 结合律:可用于不借助临时变量交换两个数:
a = a ^ b;
b = a ^ b; // b = (a^b)^b = a
a = a ^ b; // a = (a^b)^a = b数据校验:奇偶校验、简单加密
~)“0 变 1,1 变 0”对所有位进行翻转。注意:Java 使用二进制补码表示负数!
int a = 5; // 32 位: 00000000 00000000 00000000 00000101
// 取反后:
// 11111111 11111111 11111111 11111010
// 这是 -6 的补码表示!
System.out.println(~a); // 输出: -6数学关系
~N = -(N + 1)
验证:
~5 = -6
~(-3) = 2
⚠️ 不要误以为
~5 = 246(那是无符号解释),Java 中所有整数都是有符号的。
左移(<<)
所有位向左移动,低位补 0
相当于 乘以 2ⁿ(可能溢出)
int x = 4; // 0100
System.out.println(x << 2); // 010000 → 16 (4 * 2²)有符号右移(>>)
高位补符号位(正数补 0,负数补 1)
相当于 除以 2ⁿ(向下取整)
int x = -8; // ...11111000
System.out.println(x >> 2); // ...11111110 → -2无符号右移(>>>)
高位始终补 0,忽略符号
用于将负数视为无符号值处理
int x = -1; // 32 个 1
System.out.println(x >>> 30); // 000000...11 → 3🔍 对比:
System.out.println(-8 >> 1); // -4 System.out.println(-8 >>> 1); // 2147483644(大正数!)
public class BitwiseDemo {
public static void main(String[] args) {
int a = 5; // 0101
int b = 7; // 0111
System.out.println("a & b = " + (a & b)); // 5
System.out.println("a | b = " + (a | b)); // 7
System.out.println("a ^ b = " + (a ^ b)); // 2
System.out.println("~a = " + ~a); // -6
System.out.println("a << 2= " + (a << 2)); // 20
System.out.println("a >> 1= " + (a >> 1)); // 2
System.out.println("a >>>1= " + (a >>> 1)); // 2(正数时与 >> 相同)
}
}a & b = 5
a | b = 7
a ^ b = 2
~a = -6
a << 2= 20
a >> 1= 2
a >>>1= 2执行速度快:直接操作 CPU 寄存器
内存高效:多个标志可压缩到一个整数
算法简洁:某些问题(如找唯一数)用 XOR 极简解决
底层控制力强:精确操控每一位
仅适用于整数类型
负数使用补码表示,取反和右移需特别小心
可读性差:过度使用会降低代码可维护性
优先级较低:通常需加括号
// 错误:== 优先级高于 &
if (a & b == 0) { }
// 正确
if ((a & b) == 0) { }&、|、^ 是逐位逻辑运算
~ 是按位取反,结果遵循 ~N = -(N+1)
<< 左移 = 乘 2ⁿ,>> 有符号右移 = 除 2ⁿ(保留符号)
>>> 无符号右移 = 高位补 0,用于处理“无符号”场景
位运算高效但晦涩,应在必要时使用,并添加注释
如何用位运算判断一个整数是否是 2 的幂?
为什么 ~5 的结果是 -6 而不是 246?请从补码角度解释。
给定一个数组,其中只有一个数字出现一次,其余都出现两次,如何用位运算找出这个数字?
位运算符是程序员工具箱中的“精密手术刀”——不常用,但在关键时刻能解决棘手问题。理解其原理,善用其威力,你将能编写出更底层、更高效的 Java 程序。