Java中负数位移严格基于补码:>>算术右移高位补1保持负号,>>>逻辑右移高位补0必得非负数,左移统一低位补0,所有操作均直接作用于完整二进制位序列。

Java 中的位移运算符对负数的处理并非“特殊”,而是严格遵循补码表示和算术/逻辑位移的定义。关键在于:负数在 Java 中以 32 位(int)或 64 位(long)补码 形式存储,位移操作直接作用于该二进制表示,不涉及符号转换或额外规则。
负数的补码表示是理解前提
Java 中所有整数类型(byte、short、int、long)均采用补码表示有符号数。例如:
- int a = -5; 的二进制补码(32 位)为:11111111 11111111 11111111 11111011
- 最高位(第31位)为 1,表示负数;其余位由“取反加1”得到
- 位移操作的对象就是这个完整的32位(或64位)比特序列,不是其绝对值
右移运算符 >> 是算术右移(保留符号位)
对负数使用 >> 时,高位**用符号位(1)填充**,保证结果仍为负数,且数学上等价于向下取整除以 2n:
-
-8 >> 1 → 补码
11111000右移1位 →11111100= -4 -
-7 >> 2 →
11111001→11111110= -2(即 ⌊−7/4⌋ = −2) - 无论原数多大,高位始终补 1,不会变成正数
无符号右移 >>> 总是逻辑右移(高位补0)
>>> 忽略符号位含义,统一高位补 0,结果**总是非负数**(即使原操作数为负):
立即学习“Java免费学习笔记(深入)”;
-
-1 >>> 1 → 32个1右移1位 → 高位补0 → 得到
01111111...11111111= 2147483647(即 Integer.MAX_VALUE) -
-8 >>> 2 →
11111000→00111110= 62 - 注意:>>> 对正数与 >> 行为一致;对负数则彻底改变数值意义,仅用于底层比特操作
左移
无论操作数正负,都是低位补 0,高位舍弃(可能溢出):
- -4 →
11111100→11111000= -8 - -1 → 32个1左移3位 → 低3位变0,高3位丢弃 → 仍是 32个1 = -1(因溢出回绕)
- 效果等价于乘以 2n(但溢出时不满足数学乘法,只按补码循环处理)









