java整数类型统一采用二进制补码表示,因其能确保零唯一、加减运算统一、溢出行为可预测;正数直接转二进制,负数按“取反加1”计算;int范围是−2³¹到2³¹−1,负数多一个值。

Java 中的整数类型(byte、short、int、long)在内存中统一采用二进制补码(Two's Complement)表示,这不是 Java 的“选择”,而是硬件与逻辑协同的结果——它让加减运算无需区分正负,零唯一,溢出行为可预测。
为什么必须用补码?不是原码或反码
原码和反码都有“+0”和“−0”两种表示(如 8 位下:00000000 和 10000000 都代表 0),这浪费编码空间且导致比较、运算逻辑复杂。反码还需额外处理“循环进位”。而补码天然满足三个关键需求:
- 0 只有一种表示:全 0(例如
int中的00000000 00000000 00000000 00000000) - 加法器对任意两数直接相加即可,
a + (−a)自然得 0(如1 + (−1)→00000001 + 11111111 = 00000000) - 溢出时高位进位自动丢弃,结果仍在合法补码范围内(如
Integer.MAX_VALUE + 1得Integer.MIN_VALUE)
补码怎么算?正负数都清晰可推
补码不是魔术,是严格可逆的机械过程:
-
正数和零:直接转为对应位宽的二进制,高位补 0。例如
int中的 5 →00000000 00000000 00000000 00000101 -
负数:先写出其绝对值的二进制(同上补足 32 位),再逐位取反(0→1,1→0),最后整体加 1。例如 −5:
5 →00000000 00000000 00000000 00000101
取反 →11111111 11111111 11111111 11111010
加 1 →11111111 11111111 11111111 11111011
验证方法:对这个结果再执行一次“取反加 1”,应还原为原正数;或用 Integer.toBinaryString(-5) 查看(注意该方法不补前导零,但实际存储就是 32 位)。
符号位与数值范围的硬约束
int 是 32 位有符号整数,最高位(bit 31,从 0 开始编号)固定为符号位:
- 符号位为 0 → 非负数,剩余 31 位(bit 0 到 bit 30)全 1 时最大:即
2⁰ + 2¹ + … + 2³⁰ = 2³¹ − 1 = 2147483647 - 符号位为 1 → 负数,最小值不是 “−2147483647”,而是
10000000 00000000 00000000 00000000,对应十进制 −2³¹ = −2147483648 - 负数比正数多一个值,因为 0 占用了一个非负位置,所以负数范围是 −2³¹ 到 −1(共 2³¹ 个值),正数是 1 到 2³¹−1(共 2³¹−1 个值),加上 0 刚好填满 2³² 种组合
位运算与溢出:补码下的自然行为
位运算(&、|、^、~、移位)直接作用于补码比特序列:
-
~x就是按位取反,对int值 x 执行后,结果等于−x − 1(例如~5 == −6) - 左移
相当于乘以 2 的幂,右移 <code>>>是带符号除法(负数保持符号位),无符号右移>>>则高位补 0 - 溢出不是异常,而是补码加法的固有现象:当计算结果超出 [−2³¹, 2³¹−1],高位被截断,结果绕回。例如
2147483647 + 1→−2147483648
这种行为在底层高效,但业务代码中需主动防护(如使用 Math.addExact() 抛异常,或 BigInteger 避免溢出)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











