位运算
位运算
一、位运算基础概念
1.1 二进制表示
Java使用补码表示整数类型(byte/short/int/long):
- 正数:原码=反码=补码
- 负数:补码=反码+1(反码:符号位不变,其余位取反)
示例:
5 → 00000101
-5 → 11111011(8位byte类型)
1.2 位运算符概览
| 运算符 | 名称 | 示例 | 说明 |
|---|---|---|---|
& |
按位与 | a & b | 两位同时为1时结果为1 |
| |
按位或 | a|b | a、b任意一位为1时结果为1 |
^ |
按位异或 | a ^ b | 两位不同时结果为1 |
~ |
按位取反 | ~a | 所有位取反(包括符号位) |
<< |
左移位 | a << n | 左移n位,低位补0 |
>> |
带符号右移 | a >> n | 右移n位,高位补符号位 |
>>> |
无符号右移 | a >>>n | 右移n位,高位补0 |
二、基本位运算符详解
2.1 按位与(&)
特性:
- 清零特定位:
a & ~mask - 保留特定位:
a & mask
示例:
int a = 0b1100; // 12
int b = 0b1010; // 10
int result = a & b; // 0b1000 → 8
2.2 按位或(|)
特性:
- 设置特定位为1
示例:
int flags = 0;
flags |= 0b0001; // 设置第0位
flags |= 0b1000; // 设置第3位 → flags=0b1001
2.3 按位异或(^)
特性:
a ^ a = 0a ^ 0 = a- 交换变量:
a ^= b; b ^= a; a ^= b;
示例:
int x = 5; // 0101
int y = 3; // 0011
x ^= y; // 0110 → 6
y ^= x; // 0101 → 5
x ^= y; // 0011 → 3
2.4 按位取反(~)
注意: 结果与数据类型位数有关
示例:
byte a = 0b00000000; // 0
~a → 0b11111111 → -1(补码表示)
三、位移运算符
3.1 左移运算符(<<)
公式: a << n = a × 2ⁿ
特性: 可能改变符号位
示例:
int a = 0b0011; // 3
a << 2 → 0b1100 → 12
3.2 带符号右移(>>)
特性: 保持符号位不变
示例:
int a = -8; // 11111111 11111111 11111111 11111000
a >> 2 → -2 // 11111111 11111111 11111111 11111110
3.3 无符号右移(>>>)
特性: 高位始终补0
示例:
int a = -8;
a >>> 2 → 1073741822
// 00111111 11111111 11111111 11111110
四、高级技巧与应用
4.1 快速判断奇偶
boolean isEven = (n & 1) == 0; // 0为偶数,1为奇数
4.2 交换数值
a ^= b;
b ^= a;
a ^= b;
4.3 计算绝对值
int abs(int x) {
int mask = x >> 31;
return (x ^ mask) - mask;
}
4.4 查找唯一出现数字
(LeetCode 136题)
int singleNumber(int[] nums) {
int result = 0;
for (int num : nums) result ^= num;
return result;
}
4.5 位掩码权限系统
final int READ = 1; // 0001
final int WRITE = 2; // 0010
final int EXECUTE = 4; // 0100
int permissions = 0;
permissions |= READ | WRITE; // 设置读写权限
// 检查权限
boolean canRead = (permissions & READ) != 0;
4.6 位计数(Brian Kernighan算法)
int countBits(int n) {
int count = 0;
while (n != 0) {
n &= (n - 1);
count++;
}
return count;
}
五、注意事项
-
位移长度限制:实际移动位数 =
n % 32(int)或n % 64(long)int a = 1; a << 33 → 相当于 a << 1 → 2 -
符号扩展:右移运算符对符号位的处理差异
-
类型转换风险:
byte b = 0b10000000; // -128 int i = b; // -128(符号扩展) int j = b & 0xFF; // 128(无符号处理) -
优先级问题:位运算符优先级低于比较运算符
if (a & 0xFF == 0) → 错误!应改为 if ((a & 0xFF) == 0)
六、性能优化应用
6.1 快速乘除
int x = 7;
x <<= 3; // 7*8=56
x >>= 2; // 56/4=14
6.2 判断2的幂
boolean isPowerOfTwo = (n & (n - 1)) == 0 && n != 0;
6.3 颜色分量提取
int color = 0xFF336699;
int alpha = (color >>> 24) & 0xFF;
int red = (color >>> 16) & 0xFF;
int green = (color >>> 8) & 0xFF;
int blue = color & 0xFF;
七、综合应用实例
7.1 位图存储
class BitSet {
private long[] data;
public BitSet(int capacity) {
data = new long[(capacity + 63) / 64];
}
void set(int pos) {
data[pos >>> 6] |= 1L << (pos & 0x3F);
}
boolean get(int pos) {
return (data[pos >>> 6] & (1L << (pos & 0x3F))) != 0;
}
}
7.2 位反转
int reverseBits(int n) {
n = (n >>> 16) | (n << 16);
n = ((n & 0xff00ff00) >>> 8) | ((n & 0x00ff00ff) << 8);
n = ((n & 0xf0f0f0f0) >>> 4) | ((n & 0x0f0f0f0f) << 4);
n = ((n & 0xcccccccc) >>> 2) | ((n & 0x33333333) << 2);
n = ((n & 0xaaaaaaaa) >>> 1) | ((n & 0x55555555) << 1);
return n;
}
八、总结
位运算在以下场景体现优势:
- 底层系统编程
- 高性能算法优化
- 内存敏感型应用
- 加密/压缩算法
- 图形处理
注意事项:
- 优先保证代码可读性,必要时添加注释
- 谨慎处理符号位和位移操作
- 注意Java整型的固定位数特性
- 进行位操作时考虑平台差异(Java跨平台特性保证位运算一致性)

浙公网安备 33010602011771号