27. Java中,使用按位运算符和移位运算符
Java
提供了按位运算符和移位运算符,这些运算符用于直接操作整数类型的二进制位。虽然它们在日常编程中不常用,但在一些性能要求较高的应用中,例如图像处理、加密或其他低级操作中,可能会非常有用。
1. 按位补码运算符 (~
)
**按位补码运算符(~
)**会反转操作数的每一位,将 0
变为 1
,1
变为 0
。例如,如果某个整数的二进制表示是 00000000
,应用 ~
运算符后,它将变为 11111111
。
示例:
java
int number = 0x00000000; // 00000000(二进制)
int result = ~number; // 11111111(二进制)
System.out.println(result); // 输出 -1
2. 按位运算符
按位运算符用于逐位对整数类型的二进制表示进行操作。
-
按位 AND (
&
) :将两个操作数的每一位进行AND
运算,只有两个操作数的对应位都为1
时,结果才为1
。示例:
javaint a = 0x6; // 0110 int b = 0x3; // 0011 System.out.println(a & b); // 输出 2 (0010)
-
按位 OR (
|
) :将两个操作数的每一位进行OR
运算,只要两个操作数的对应位有一个为1
,结果就为1
。示例:
javaint a = 0x6; // 0110 int b = 0x3; // 0011 System.out.println(a | b); // 输出 7 (0111)
-
按位 XOR (
^
) :将两个操作数的每一位进行 XOR 运算,只有两个操作数的对应位不相同时,结果才为1
。示例:
javaint a = 0x6; // 0110 int b = 0x3; // 0011 System.out.println(a ^ b); // 输出 5 (0101)
3. 移位运算符
-
左移运算符 (
<<
):将操作数的位向左移动指定的位数。左移操作会将零填充到最右侧。示例:
javaint a = 5; // 二进制表示为 0000000000000101 System.out.println(a << 1); // 输出 10 (0000000000001010)
-
有符号右移 (
>>
) :将操作数的位向右移动指定的位数。右移时,符号位会被扩展。如果原数是正数,左侧填充0
;如果是负数,左侧填充1
。示例:
javaint a = -8; // 二进制表示为 1111 1111 1111 1111 1111 1111 1111 1000 System.out.println(a >> 2); // 输出 -2 (1111 1111 1111 1111 1111 1111 1111 1110)
步骤 1:确定 -8 的二进制补码表示
在
Java
中,int
类型是32
位有符号整数,负数以补码形式存储。求-8
的补码步骤如下:- 先求 8 的二进制原码 :8 的二进制表示为
0000 0000 0000 0000 0000 0000 0000 1000
。 - 对原码取反 :得到反码
1111 1111 1111 1111 1111 1111 1111 0111
。 - 反码加 1 :得到 -8 的补码
1111 1111 1111 1111 1111 1111 1111 1000
。
步骤 2:进行有符号右移操作
有符号右移运算符
>>
会将二进制数向右移动指定的位数,同时保持符号位不变。这里要将-8
的补码右移2
位,即1111 1111 1111 1111 1111 1111 1111 1000
右移 2 位。- 右边移出的两位(最低的两个
0
)被丢弃。 - 左边空出的两位用符号位(最高位的
1
)填充,得到1111 1111 1111 1111 1111 1111 1111 1110
。
步骤 3:将右移后的补码转换为十进制数
右移后的结果
1111 1111 1111 1111 1111 1111 1111 1110
是补码形式,要得到其十进制值,需将补码转换为原码,步骤如下:- 补码减 1 :得到反码
1111 1111 1111 1111 1111 1111 1111 1101
。 - 反码取反 :得到原码
1000 0000 0000 0000 0000 0000 0000 0010
,其十进制值为 -2。
- 先求 8 的二进制原码 :8 的二进制表示为
-
无符号右移 (
>>>
):将操作数的位向右移动指定的位数,左侧始终填充 0。示例:
javaint a = -8; // 二进制表示为 1111111111111000 System.out.println(a >>> 2); // 输出 1073741822 (00111111111111111111111111111110)
步骤 1:确定 -8 的二进制补码表示
在 Java 里,
int
类型为 32 位有符号整数,负数以补码形式存储。求 -8 的补码可按以下步骤进行:- 得出 8 的二进制原码 :8 的二进制表示是
0000 0000 0000 0000 0000 0000 0000 1000
。 - 对原码取反 :得到反码
1111 1111 1111 1111 1111 1111 1111 0111
。 - 反码加 1 :得到
-8
的补码1111 1111 1111 1111 1111 1111 1111 1000
。
步骤 2:执行无符号右移操作
无符号右移运算符
>>>
会二进制数向右移动指定的位数,无论该数是正数还是负数,左边空出的位都用0
填充。这里要把-8
的补码右移2
位,也就是对1111 1111 1111 1111 1111 1111 1111 1000
进行右移操作。- 右边移出的两位(最低的两个
0
)被丢弃。 - 左边空出的两位用
0
填充,得到0011 1111 1111 1111 1111 1111 1111 1110
。
步骤 3:将右移后的二进制数转换为十进制数
右移后的结果
0011 1111 1111 1111 1111 1111 1111 1110
最高位是 0,表示这是一个正数,可通过按位权展开来计算其十进制值: - 得出 8 的二进制原码 :8 的二进制表示是
4. 按位运算符示例:按位 AND 运算符
下面的 BitDemo
程序演示了如何使用按位 AND 运算符将数字 2
打印到标准输出:
java
class BitDemo {
public static void main(String[] args) {
int bitmask = 0x000F; // 0000 0000 0000 1111(十六进制掩码)
int val = 0x2222; // 0010 0010 0010 0010(十六进制数值)
// 使用按位 AND 运算符
System.out.println(val & bitmask); // 输出 2 (二进制 0000 0010)
}
}
程序输出:
java
2
解释:
bitmask = 0x000F
:这是一种掩码,它的二进制表示是0000 0000 0000 1111
。这意味着它只保留了整数的低 4 位。val = 0x2222
:这是一个十六进制数,二进制表示为0010 0010 0010 0010
。- 按位 AND 运算 :通过
val & bitmask
,我们将val
和bitmask
进行按位与运算,结果为2
,因为只有val
的低 4 位与bitmask
的低 4 位对齐。
总结
- 按位运算符 (
&
,|
,^
,~
)允许我们直接操作整数的二进制位,适用于低级操作和性能优化。 - 移位运算符 (
<<
,>>
,>>>
)用于将二进制位向左或向右移动,适用于位移操作或快速乘除。 - 这些运算符有助于进行更加精细的位级控制,例如在图像处理、加密和算法优化中常见。
虽然这些运算符在常规应用中不太常用,但在需要处理二进制数据时,它们是非常强大的工具。