-integer.min_value仍为integer.min_value,因int用32位补码表示,-(-2³¹)数学结果2³¹超出int正数上限2³¹−1,溢出后模2³²绕回得原值0x80000000。

Java中int类型是32位有符号整数,取值范围为-2147483648到2147483647。对边界值取反(即使用一元负号-)时,符号位变化会引发溢出,导致结果不符合直觉——尤其是对最小值Integer.MIN_VALUE取反仍得它本身。
为什么-Integer.MIN_VALUE还是Integer.MIN_VALUE?
因为int采用补码表示:
- Integer.MIN_VALUE 是 0x80000000(二进制 1000...000),即 -2³¹;
- 对其取反(求负)在数学上应为 +2³¹,但该值已超出int最大正数(2³¹−1 = 2147483647);
- 补码系统下,溢出后自动“绕回”,结果仍是 0x80000000,即 -2147483648。
常见边界取反行为对照
注意:以下结果均在int范围内直接运算得出,未做类型提升或检查:
-
-Integer.MAX_VALUE→-2147483647(正确,因 2147483647 可被表示为负数) -
-Integer.MIN_VALUE→-2147483648(溢出,结果不变) -
-(-2147483648)→-2147483648(同上,编译期常量也如此)
安全处理方案
若业务逻辑需避免此溢出陷阱,可借助更大范围类型或显式检查:
- 用
long临时承载:long result = -(long) value;,再判断是否超出int范围 - 提前校验最小值:
if (value == Integer.MIN_VALUE) throw new ArithmeticException("Negation overflow"); - 使用
Math.negateExact(int)(Java 8+):自动抛出ArithmeticException而非静默溢出
底层本质是补码算术的确定性行为
这不是Bug,而是补码设计的必然结果:符号位参与运算,且加法/取反均按模 2³² 运行。JVM规范明确要求整数运算发生溢出时不抛异常,而是保留低32位——这正是-Integer.MIN_VALUE恒等于自身的根本原因。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











