Java 位运算详解
位运算是直接对二进制位进行操作的一种运算方式。它高效、底层,常用于优化性能、底层开发和算法实现。Java 提供了丰富的位运算操作符。
1. 位运算符概览
运算符 | 名称 | 描述 |
---|---|---|
& | 按位与(AND) | 两个位都为 1,则结果为 1;否则结果为 0。 |
| | 按位或(OR) | 两个位只要有一个为 1,则结果为 1。 |
^ | 按位异或(XOR) | 两个位相同为 0,不同为 1。 |
~ | 按位取反(NOT) | 将每个位的值取反,0 变 1,1 变 0。 |
<< | 左移 | 将数的二进制位整体左移,右侧补 0。 |
>> | 右移 | 将数的二进制位整体右移,左侧用符号位填充(保留正负号)。 |
>>> | 无符号右移 | 将数的二进制位整体右移,左侧始终补 0(不保留正负号)。 |
2. 各运算符详解
2.1 按位与(&
)
- 规则:对应位都为 1,结果才为 1。
- 作用:常用于掩码操作或判断某个位是否为 1。
示例:
int a = 5; // 二进制:0101
int b = 3; // 二进制:0011
int result = a & b; // 二进制:0001
System.out.println(result); // 输出:1
应用:
- 判断某个位是否为 1。
int n = 5; // 二进制:0101
if ((n & 1) == 1) {System.out.println("最低位是 1");
}
2.2 按位或(|
)
- 规则:对应位只要有一个为 1,结果为 1。
- 作用:常用于设置某些位为 1。
示例:
int a = 5; // 二进制:0101
int b = 3; // 二进制:0011
int result = a | b; // 二进制:0111
System.out.println(result); // 输出:7
应用:
- 设置某个位为 1。
int n = 5; // 二进制:0101
int mask = 2; // 二进制:0010
int result = n | mask; // 二进制:0111
System.out.println(result); // 输出:7
2.3 按位异或(^
)
- 规则:对应位相同为 0,不同为 1。
- 作用:用于交换变量或加密操作。
示例:
int a = 5; // 二进制:0101
int b = 3; // 二进制:0011
int result = a ^ b; // 二进制:0110
System.out.println(result); // 输出:6
应用:
- 交换两个变量(无需临时变量)。
int a = 5, b = 3;
a = a ^ b; // a = 0101 ^ 0011 = 0110
b = a ^ b; // b = 0110 ^ 0011 = 0101
a = a ^ b; // a = 0110 ^ 0101 = 0011
System.out.println("a = " + a + ", b = " + b); // 输出:a = 3, b = 5
2.4 按位取反(~
)
- 规则:将每个位取反,0 变 1,1 变 0。
- 作用:求补码(通常用于负数表示)。
示例:
int a = 5; // 二进制:00000000 00000000 00000000 00000101
int result = ~a; // 取反:11111111 11111111 11111111 11111010
System.out.println(result); // 输出:-6
注意:
- Java 中使用二进制补码表示有符号整数,因此取反结果包含符号。
2.5 左移(<<
)
- 规则:将数的二进制位整体左移,右侧补 0。
- 作用:用于快速乘以 2 n 2^n 2n。
示例:
int a = 5; // 二进制:0101
int result = a << 2; // 左移两位:010100
System.out.println(result); // 输出:20
应用:
- 计算 2 n 2^n 2n。
int n = 3;
System.out.println(1 << n); // 输出:8
2.6 右移(>>
)
- 规则:将数的二进制位整体右移,左侧用符号位填充(正数补 0,负数补 1)。
- 作用:用于快速除以 2 n 2^n 2n,保留正负号。
示例:
int a = 20; // 二进制:00010100
int result = a >> 2; // 右移两位:00000101
System.out.println(result); // 输出:5
应用:
- 除法运算(对 2 的幂次方)。
int n = 16;
System.out.println(n >> 2); // 输出:4
2.7 无符号右移(>>>
)
- 规则:将数的二进制位整体右移,左侧始终补 0(无符号)。
- 作用:处理无符号数据。
示例:
int a = -20; // 二进制:11111111 11111111 11111111 11101100
int result = a >>> 2; // 无符号右移两位:00111111 11111111 11111111 11111011
System.out.println(result); // 输出:1073741819
3. 位运算的应用场景
3.1 判断奇偶
- 原理:二进制奇数的最低位为 1,偶数最低位为 0。
if ((n & 1) == 0) {System.out.println("偶数");
} else {System.out.println("奇数");
}
3.2 交换两个数
int a = 5, b = 3;
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println("a = " + a + ", b = " + b);
3.3 求绝对值
- 原理:负数的符号位为 1,正数的符号位为 0。
int n = -5;
int result = (n ^ (n >> 31)) - (n >> 31);
System.out.println(result); // 输出:5
3.4 快速计算 2 的幂次方
int n = 4;
System.out.println(1 << n); // 输出:16
3.5 清除最低位的 1
- 原理:
n & (n - 1)
将最低位的 1 清为 0。
int n = 10; // 二进制:1010
int result = n & (n - 1); // 二进制:1000
System.out.println(result); // 输出:8
3.6 统计二进制中 1 的个数
int count = 0;
int n = 7; // 二进制:0111
while (n != 0) {n = n & (n - 1);count++;
}
System.out.println(count); // 输出:3
3.7 判断一个数是否为 2 的幂
- 原理:2 的幂次方数的二进制中只有一个 1。
if ((n > 0) && (n & (n - 1)) == 0) {System.out.println("是 2 的幂次方");
}
4. 总结
位运算符对比
运算符 | 作用 | 常见应用场景 |
---|---|---|
& | 按位与 | 判断奇偶、掩码操作 |
` | ` | 按位或 |
^ | 按位异或 | 交换变量、加密解密 |
~ | 按位取反 | 求补码、负数表示 |
<< | 左移 | 快速乘以 2 的幂 |
>> | 右移 | 快速除以 2 的幂,保留符号 |
>>> | 无符号右移 | 处理无符号数据(例如负数二进制操作) |
位运算直接操作二进制位,是一种底层优化手段,在性能要求高、资源受限的场景(如嵌入式开发、算法设计)尤为常用。