Java位运算符 #
一、位运算符概述 #
位运算符直接对整数的二进制位进行操作,效率极高。
| 运算符 | 说明 | 示例 |
|---|---|---|
| & | 按位与 | 5 & 3 = 1 |
| | | 按位或 | 5 | 3 = 7 |
| ^ | 按位异或 | 5 ^ 3 = 6 |
| ~ | 按位取反 | ~5 = -6 |
| << | 左移 | 5 << 1 = 10 |
| >> | 右移 | 5 >> 1 = 2 |
| >>> | 无符号右移 | -5 >>> 1 |
二、按位运算 #
2.1 按位与(&) #
对应位都为1时结果为1,否则为0。
java
int a = 5; // 二进制: 0101
int b = 3; // 二进制: 0011
int c = a & b; // 结果: 0001 = 1
System.out.println(c); // 1
/*
0101 (5)
& 0011 (3)
----
0001 (1)
*/
2.2 按位或(|) #
对应位有一个为1结果就为1。
java
int a = 5; // 二进制: 0101
int b = 3; // 二进制: 0011
int c = a | b; // 结果: 0111 = 7
System.out.println(c); // 7
/*
0101 (5)
| 0011 (3)
----
0111 (7)
*/
2.3 按位异或(^) #
对应位不同时结果为1,相同时为0。
java
int a = 5; // 二进制: 0101
int b = 3; // 二进制: 0011
int c = a ^ b; // 结果: 0110 = 6
System.out.println(c); // 6
/*
0101 (5)
^ 0011 (3)
----
0110 (6)
*/
异或特性:
- 任何数与0异或,结果为原数:
a ^ 0 = a - 任何数与自身异或,结果为0:
a ^ a = 0 - 异或满足交换律和结合律
java
// 交换两个数(不使用临时变量)
int x = 5, y = 3;
x = x ^ y; // x = 5 ^ 3
y = x ^ y; // y = (5 ^ 3) ^ 3 = 5
x = x ^ y; // x = (5 ^ 3) ^ 5 = 3
System.out.println(x + ", " + y); // 3, 5
2.4 按位取反(~) #
将每一位取反(0变1,1变0)。
java
int a = 5; // 二进制: 0000...0101
int b = ~a; // 二进制: 1111...1010 = -6
System.out.println(b); // -6
// 公式:~a = -(a + 1)
三、移位运算 #
3.1 左移(<<) #
将二进制位向左移动,低位补0。
java
int a = 5; // 二进制: 0101
int b = a << 1; // 二进制: 1010 = 10
int c = a << 2; // 二进制: 10100 = 20
System.out.println(b); // 10
System.out.println(c); // 20
// 左移n位相当于乘以2^n
// 5 << 1 = 5 * 2 = 10
// 5 << 2 = 5 * 4 = 20
3.2 右移(>>) #
将二进制位向右移动,高位补符号位(算术右移)。
java
int a = 10; // 二进制: 1010
int b = a >> 1; // 二进制: 0101 = 5
int c = a >> 2; // 二进制: 0010 = 2
System.out.println(b); // 5
System.out.println(c); // 2
// 右移n位相当于除以2^n(向下取整)
// 10 >> 1 = 10 / 2 = 5
// 10 >> 2 = 10 / 4 = 2
// 负数右移
int d = -10; // 二进制: 1111...0110
int e = d >> 1; // 二进制: 1111...1011 = -5
System.out.println(e); // -5
3.3 无符号右移(>>>) #
将二进制位向右移动,高位补0(逻辑右移)。
java
int a = -10;
int b = a >> 1; // 算术右移,高位补符号位
int c = a >>> 1; // 无符号右移,高位补0
System.out.println(b); // -5
System.out.println(c); // 2147483643
// 正数时 >> 和 >>> 结果相同
int d = 10;
System.out.println(d >> 1); // 5
System.out.println(d >>> 1); // 5
四、位运算应用 #
4.1 判断奇偶 #
java
public static boolean isOdd(int n) {
return (n & 1) == 1;
}
System.out.println(isOdd(5)); // true
System.out.println(isOdd(4)); // false
4.2 交换两数 #
java
public static void swap(int[] arr, int i, int j) {
if (i != j) {
arr[i] ^= arr[j];
arr[j] ^= arr[i];
arr[i] ^= arr[j];
}
}
4.3 取绝对值 #
java
public static int abs(int n) {
int mask = n >> 31; // 符号位扩展
return (n ^ mask) - mask;
}
4.4 判断是否为2的幂 #
java
public static boolean isPowerOfTwo(int n) {
return n > 0 && (n & (n - 1)) == 0;
}
System.out.println(isPowerOfTwo(8)); // true
System.out.println(isPowerOfTwo(6)); // false
4.5 计算二进制中1的个数 #
java
public static int countOnes(int n) {
int count = 0;
while (n != 0) {
n &= (n - 1); // 清除最低位的1
count++;
}
return count;
}
System.out.println(countOnes(7)); // 3 (111)
System.out.println(countOnes(10)); // 2 (1010)
// Java内置方法
System.out.println(Integer.bitCount(7)); // 3
4.6 权限管理 #
java
public class Permission {
public static final int READ = 1; // 0001
public static final int WRITE = 2; // 0010
public static final int EXECUTE = 4; // 0100
public static final int DELETE = 8; // 1000
private int permissions = 0;
// 添加权限
public void add(int permission) {
permissions |= permission;
}
// 移除权限
public void remove(int permission) {
permissions &= ~permission;
}
// 检查权限
public boolean has(int permission) {
return (permissions & permission) != 0;
}
}
// 使用
Permission p = new Permission();
p.add(Permission.READ | Permission.WRITE);
System.out.println(p.has(Permission.READ)); // true
System.out.println(p.has(Permission.EXECUTE)); // false
4.7 快速乘除 #
java
// 乘以2
int a = 5;
int b = a << 1; // 10
// 除以2
int c = a >> 1; // 2
// 乘以2的n次方
int d = a << 3; // 5 * 8 = 40
// 取模(当除数是2的幂时)
int mod = a & 3; // a % 4
4.8 颜色处理 #
java
// RGB颜色
int color = 0xFF8000; // 橙色
// 提取RGB分量
int red = (color >> 16) & 0xFF; // 255
int green = (color >> 8) & 0xFF; // 128
int blue = color & 0xFF; // 0
// 合并RGB
int newColor = (red << 16) | (green << 8) | blue;
五、位运算技巧 #
5.1 获取最低位1 #
java
int n = 12; // 1100
int lowestOne = n & (-n); // 4 (0100)
5.2 清除最低位1 #
java
int n = 12; // 1100
int cleared = n & (n - 1); // 8 (1000)
5.3 翻转最低位1 #
java
int n = 12; // 1100
int flipped = n ^ (n - 1); // 0111
5.4 取反特定位 #
java
int n = 12; // 1100
int mask = 0b0011;
int result = n ^ mask; // 1111 = 15
六、注意事项 #
6.1 移位范围 #
java
// int类型移位,实际移动位数 = n % 32
int a = 1;
int b = a << 32; // 相当于 << 0,结果还是1
int c = a << 33; // 相当于 << 1,结果是2
// long类型移位,实际移动位数 = n % 64
long l = 1L;
long m = l << 64; // 相当于 << 0,结果还是1
6.2 符号扩展 #
java
byte b = -1; // 11111111
int i = b; // 11111111 11111111 11111111 11111111(符号扩展)
// 避免符号扩展
int j = b & 0xFF; // 00000000 00000000 00000000 11111111 = 255
6.3 优先级 #
java
// 位运算优先级低于算术运算
int a = 5 + 3 & 2; // (5 + 3) & 2 = 8 & 2 = 0
int b = 5 + (3 & 2); // 5 + 2 = 7
// 建议使用括号明确优先级
七、总结 #
| 运算符 | 说明 | 应用场景 |
|---|---|---|
| & | 按位与 | 掩码操作、清零、判断奇偶 |
| | | 按位或 | 设置位、权限组合 |
| ^ | 按位异或 | 交换、加密、去重 |
| ~ | 按位取反 | 取反操作 |
| << | 左移 | 乘以2的幂 |
| >> | 右移 | 除以2的幂 |
| >>> | 无符号右移 | 无符号除法 |
位运算要点:
- 位运算效率高,适合性能敏感场景
- 注意符号位和移位范围
- 使用括号明确优先级
- 常用于权限、状态、算法优化
最后更新:2026-03-26