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

Java long字面量与final常量乘法结果为何不一致?

运行结果差异原因

Java中算术运算的类型由参与运算的操作数本身的静态类型决定,和最终赋值的变量类型、变量是否被final修饰没有直接关联,两个结果不一致的核心原因是两次乘法的操作数类型完全不同:


c的计算逻辑(溢出得到负数)

  • 代码中无后缀的整数字面量123123默认是32位int类型,取值范围仅为-2147483648 ~ 2147483647。
  • 表达式123123*123123*123123的三个操作数全是int类型,因此整个乘法全程按int规则运算:第一步计算123123 * 123123得到15159273129,已经远超int最大值,直接触发int溢出,后续乘法用溢出后的int值继续计算,最终得到int结果-162426261。
  • 这个溢出后的int结果最后才会隐式转换为long赋值给c,溢出早已发生,和是否编译期计算无关——哪怕编译期做常量折叠,也是按int类型算完溢出的结果再赋值,结果不会改变。

d的计算逻辑(得到正确结果)

  • 变量b是被final long修饰的编译期常量,静态类型明确是64位long,long的取值范围最大可达9223372036854775807,完全可以容纳123123的三次方结果。
  • 表达式b*b*b的三个操作数全是long类型,乘法全程按long规则运算,不会触发int层面的溢出,最终得到正确值1866455185461867。这个计算同样会在编译期完成常量折叠,只是运算采用的类型是long,结果自然正确。

原有认知的偏差

你之前认为「final修饰long变量后编译期运算结果应该一致」的问题,是混淆了常量折叠的规则和类型提升规则:

  • 编译期确实会对final基本类型常量、字面量表达式直接计算结果,但计算时严格遵守Java的类型规则,不会因为最终要赋值给long变量,就自动把表达式里的int操作数提升为long。
  • 如果要让c的结果和d一致,只需要给第一个字面量加上long后缀L,把第一个操作数标记为long类型即可,比如写成final long c = 123123L * 123123 * 123123;,后续的int操作数会自动提升为long参与运算,就不会出现int溢出了。

内容的提问来源于stack exchange,提问作者bc a

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 22:45:44