java中负数位移基于补码:>>算术右移高位补1保持负号,>>>逻辑右移高位补0必得非负数,左移统一低位补0,所有操作均直接作用于32/64位补码序列。

Java 中移位运算符处理负数时,核心是**补码表示法**和**算术右移(>>)与逻辑右移(>>>)的区别**。负数在 Java 中统一用 32 位(int)或 64 位(long)补码存储,移位操作直接在该二进制形式上进行,不转换为正数再计算。
负数的补码怎么来的?
以 int 类型的 -5 为例:
- 5 的原码(32 位):00000000 00000000 00000000 00000101
- 取反(得反码):11111111 11111111 11111111 11111010
- 加 1(得补码):11111111 11111111 11111111 11111011
这个补码就是 -5 在内存中的真实二进制表示,所有移位操作都基于它。
左移(
左移
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- -5 :补码 11111111...11111011 左移 1 位 → 11111111...11110110,即 -10
- -5 :得到 -20
- 但注意:-5 会把原来最高位的 1 移出,低位补 0,结果变成一个很大的正数(如 0x40000000 = 1073741824)
左移等价于乘以 2 的幂(不溢出时),但溢出后结果不可预测(因 Java 不检查整数溢出)。
右移:>> 和 >>> 的关键区别
>> 是算术右移:高位**补符号位**(负数补 1,正数补 0),保持符号不变,等价于“向下取整的除法”。
- -5 >> 1:补码 11111111...11111011 右移 1 位 → 高位补 1 → 11111111...11111101 = -3
- -5 >> 2 → -2(不是 -1.25 向下取整为 -2)
>>> 是逻辑右移:高位**无条件补 0**,结果一定非负,彻底丢弃原符号信息。
- -5 >>> 1:补码右移 1 位,高位补 0 → 01111111...11111101 = 2147483645(即 Integer.MAX_VALUE - 2)
- -1 >>> 1 = 0x7FFFFFFF = 2147483647
实用建议
- 对负数做除法近似,优先用 >>(如
n >> 1替代n / 2),但注意它是向下取整(-5/2=-2.5 → -3) - 需要无符号右移(比如解析字节流、位掩码操作),必须用 >>>
- 避免对负数使用 做“放大”用途,容易因溢出导致符号翻转,逻辑难维护
- 调试时可用
Integer.toBinaryString(x)查看补码(注意它不显示高位 0 或符号扩展,需手动补全 32 位理解)
理解补码是前提,移位只是对那一串 0/1 的机械操作 —— 没有特殊规则,只有统一规则下的自然结果。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










