1. 按位操作符(Bitwise Operators)
定义
按位操作符用于操作整数基本类型中的单个“比特”(bit),即二进制位。它们会对两个参数中对应的位执行布尔代数运算,并最终生成一个结果。
背景:按位操作符来源于 C 语言面向底层的操作,在这种操作中经常需要直接操纵硬件、设置硬件寄存器内的二进制位。不过在当前的 Java 开发过程中并不会过多用到位运算,仅供了解。
运算原理
| 操作符 | 名称 | 运算规则 |
|---|---|---|
& | 按位与 | 两个输入位都是 1,则输出 1;否则输出 0 |
| ` | ` | 按位或 |
^ | 按位异或 | 两个输入位相同(都是 0 或都是 1)则输出 0;不同时输出 1 |
~ | 按位非(取反) | 生成与输入位相反的值(0→1,1→0) |
操作符特性
- 一元 vs 二元:
~是一元操作符,只能对一个操作数进行操作;其他按位操作符是二元操作符 - 复合赋值:
&=、|=和^=都是合法的 - 限制:由于
~是一元操作符,所以不可与=联合使用
布尔类型支持
- 可执行按位
&、|和^运算 - 不能执行按位
~(为了避免与逻辑 NOT 混淆)
示例代码
public class BitwiseOperators {
public static void main(String[] args) {
int i = 666;
System.out.println(Integer.toBinaryString(i)); // 1010011010
int j = 777;
System.out.println(Integer.toBinaryString(j)); // 1100001001
System.out.println("===========按位运算符=============");
// 按位与 &
System.out.println("按位与& :" + Integer.toBinaryString(i & j)); // 1000001000
// 按位或 |
System.out.println("按位或| :" + Integer.toBinaryString(i | j)); // 1110011011
// 按位异或 ^
System.out.println("按位异或^ :" + Integer.toBinaryString(i ^ j)); // 110010011
System.out.println("===========按位运算符=============");
}
}
2. 移位操作符(Shift Operators)
定义
移位操作符操作的运算对象也是二进制的“位”,并且只可以用来处理整数类型(基本类型的一种)。
运算原理
| 操作符 | 名称 | 运算规则 |
|---|---|---|
<< | 左移位 | 按右侧指定的位数将左侧操作数向左移动,在低位补 0 |
>> | 有符号右移 | 按右侧指定的位数将左侧操作数向右移动,使用“符号扩展”(正数高位补 0,负数高位补 1) |
>>> | 无符号右移 | 按右侧指定的位数将左侧操作数向右移动,使用“零扩展”(无论正负,高位都补 0) |
注意:
>>>操作符在 C 或 C++ 中没有,是 Java 特有的。
类型转换规则
对 char、byte 和 short 类型:
- 移位前会先被转换成
int类型 - 结果也是
int类型的值 - 只有数值右端的低 5 位才有用(因为 2⁵ = 32,而 int 型只有 32 位)
对 long 类型:
- 结果也是
long类型 - 只有数值右端的低 6 位才有用(因为 2⁶ = 64,而 long 型有 64 位)
复合赋值与注意事项
- 合法操作:
<<=、>>=和>>>=都是合法的 - 潜在问题:对
byte和short值使用>>>=时,可能得到不正确的结果:- 先转成
int类型 - 进行右移操作
- 然后被截断并赋值给原来的类型
- 在这种情况下可能得到
-1的结果
- 先转成
示例代码
public class ShiftOperators {
public static void main(String[] args) {
// int 类型
int i = -1;
System.out.println("int i 移位运算符 :" + Integer.toBinaryString(i));
i >>>= 10;
System.out.println("int i 移位运算符 :" + Integer.toBinaryString(i));
System.out.println("=============================");
// long 类型
long j = -1;
System.out.println("long j 移位运算符 :" + Long.toBinaryString(j));
j >>>= 10;
System.out.println("long j 移位运算符 :" + Long.toBinaryString(j));
System.out.println("=============================");
// short 类型(注意结果)
short s = -1;
System.out.println("short s 移位运算符 :" + Integer.toBinaryString(s));
s >>>= 10;
System.out.println("short s 移位运算符 :" + Integer.toBinaryString(s));
System.out.println("=============================");
// byte 类型(注意结果)
byte b = -1;
System.out.println("byte b 移位运算符 :" + Integer.toBinaryString(b));
b >>>= 10;
System.out.println("byte b 移位运算符 :" + Integer.toBinaryString(b));
}
}
输出结果说明:
int和long类型的无符号右移能正确显示结果short和byte类型由于类型转换和截断,结果显示为全 1(即 -1)