java中负数位移的符号位处理由运算符决定:>>算术右移高位补1保持负号,>>>无符号右移高位补0结果必非负;左移

Java 位移运算中,负数的符号位扩展差异完全取决于你用的是 >> 还是 >>>——不是“怎么处理”,而是“由运算符定义好怎么处理”:前者保留符号位、后者彻底忽略。
算术右移 >>:高位补 1,保持负号
对负数执行 >> 时,Java 把整个 32 位(int)补码序列向右移动,空出的高位**一律填原符号位的值(即 1)**。结果仍是负数,数学上等价于向下取整除以 2ⁿ:
- -8 的补码是
11111111 11111111 11111111 11111000,-8 >> 1→ 高位补 1 →11111111 11111111 11111111 11111100= -4 - -7 >> 2 → 补码右移两位后高位补两个 1 → 结果为 -2(即 ⌊−7/4⌋)
- 无论移多少位,只要用 >>,负数永远不会变正
无符号右移 >>>:高位强制补 0,结果必为非负
>>> 不关心“这是负数”,只把操作数的完整二进制位(32 位 int 或 64 位 long)当作一串纯比特来操作:右移后空出的高位**全部填 0**。因最高位变成 0,解释为有符号整数时,结果一定 ≥ 0:
- -1 的补码是 32 个 1,
-1 >>> 1→ 高位补 0 →01111111...11111111= 2147483647(Integer.MAX_VALUE) - -8 >>> 2 → 补码右移两位,高位补两个 0 → 得到 1073741822(不是 2,也不是绝对值除法)
- 即使原数是 byte 类型(如
(byte)0xFF),也会先提升为 int 再执行 >>>,所以务必注意类型提升带来的高位冗余
左移
对正负数一视同仁:低位补 0,高位舍弃。效果近似乘以 2ⁿ,但不检查溢出,也不做符号扩展:
- -4 11111100 → 左移后
11111000= -8 - -1
- 1
关键提醒:别混淆类型提升和语义意图
byte/short 参与位移前会自动提升为 int,这个过程自带符号扩展。比如:
-
byte b = (byte)0x80; b >>> 1实际是0xFFFFFF80 >>> 1= 0x7FFFFFC0,不是期望的 0x40 - 正确写法是:
(b & 0xFF) >>> 1,先清除高位扩展的 1,再无符号右移 - long 类型必须显式写
-1L >>> n,否则按 int 处理,易出错
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











