You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何2^32范围内整数溢出未抛出ArithmeticException异常?

为什么int相乘溢出没抛ArithmeticException反而得到负数?

嘿,这个问题我碰到过好多次了,咱们一步步来理清楚:

  • Java里整数运算的溢出是「静默式」的:
    当你用int这类基础整数类型做运算时,如果结果超出了类型的取值范围,Java不会主动抛出ArithmeticException,而是直接把结果高位截断,只保留对应类型位数的低部分(比如int是32位,就留低32位),这就是大家常说的「环绕溢出」。

  • 你的例子具体拆解:
    65535的十六进制是0xFFFF,它的平方是0xFFFF * 0xFFFF = 0xFFFFFFFFFFFF。但int只能存32位,所以会砍掉高位,只留低32位的数值。换算成十进制更直观:65535×65535=4294836225,而int的最大值是2147483647,这个结果比2^32(4294967296)小一点,用4294836225减去4294967296,得到的就是-131071——也就是你看到的那个奇怪的负数,这是截断后按补码规则解析出来的结果。

  • 你说的「赋值超范围抛异常」是另一种场景:
    要是你直接给int赋值一个超出范围的字面量(比如int x = 2147483648;),编译器直接就会报错,因为这个数根本塞不进int里。但运算时的溢出不一样,Java默认不做溢出检查——这是语言设计时为了性能考虑的选择,总不能每次加减乘除都额外做一次范围判断吧?

  • 想让溢出时抛异常?有办法:
    如果你希望运算溢出时立刻抛出ArithmeticException,可以用java.lang.Math里的multiplyExact、addExact这些方法,比如把你的代码改成这样:

    int x = 65535;
    System.out.println(Math.multiplyExact(x, x));
    

    这时候运行就会抛出ArithmeticException: integer overflow,完全符合你预期的异常行为。

内容的提问来源于stack exchange,提问作者Henry Li

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:23:58