是算术右移(符号位扩展),>>>是逻辑右移(高位补0);负数时>>保持负号,>>>转为正数,如-8>>1=-4,-8>>>1=2147483644。

Java 里 、<code>>>、>>> 不是“移动数字”,而是移动二进制位 —— 负数处理方式不同,这是最常出错的地方。
为什么 >> 和 >>> 对负数结果完全不同
Java 用补码存整数,最高位是符号位。>> 是算术右移:符号位不变,空出的高位全补原符号位(负数补 1);>>> 是逻辑右移:不管正负,空出的高位一律补 0。
常见错误现象:-8 >> 1 得 -4,但 -8 >>> 1 得 2147483644(即 0x7FFFFFFC),不是你直觉里的 “除以 2”。
-
-1 >> 1→ 还是-1(全 1 补 1) -
-1 >>> 1→2147483647(0x7FFFFFFF,最高位变 0) - 只对
int/long有效;byte/short会先提升为int再运算,注意隐式类型转换
看似安全,其实也有溢出陷阱
左移本质是乘以 2 的幂,但不检查溢出。移位后超出类型范围时,高位直接截断,不报错也不提示。
立即学习“Java免费学习笔记(深入)”;
使用场景:快速乘 2 的幂、构造掩码(如 1 表示 8)、设置某一位。
1 在 <code>int中是-2147483648(符号位被置 1)1 对 <code>int等价于1 (因为只取低 5 位作为移位数),结果是 <code>1-
long移位数取低 6 位,所以1L 实际是 <code>1L → <code>1L
什么时候必须用 >>> 而不是 >>
当你在处理无符号语义的数据时,比如解析网络字节流、读取图像像素、实现哈希算法或做位掩码计算 —— 这些场景里,你关心的是原始比特,不是“这个数是正是负”。
典型例子:把一个 byte 当作 0~255 的值来用:
byte b = (byte)0xFF; // 实际值是 -1 int unsigned = b & 0xFF; // 正确:255 int wrong = b >> 4; // 错误:-1,因为 -1 >> 4 还是 -1 int right = b >>> 4; // 正确:15(0xFF >>> 4 == 0x0F)
-
>>>在int上永远返回非负数;>>可能保持负号 - 对
long同理,但要注意>>>在long上操作的是 64 位,别和int混用导致高位污染 - 不要对负的移位数使用,行为未定义(实际是取模后移位,但容易误判)
真正难的不是记住符号,而是在读别人代码或调试位运算时,一眼看出某个 >> 是不是该换成 >>> —— 尤其当变量来源复杂、类型隐式提升过多次的时候。










