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

Java中2L与2的表达式差异及溢出问题解析

两个Java语句的区别与溢出问题解析

先来看你给出的两段代码:

sum=(sum+2L*(A.length-count1[i])*count1[i])%1000000007; 
sum=(sum+2*(A.length-count1[i])*count1[i])%1000000007; 

你的疑问是:

请问上述两个语句有什么区别?这与溢出问题存在怎样的关联?
已知:count1为整数类型数组,sum为long类型。
第一条语句可使代码通过提交,但第二条语句在部分场景下会引发溢出。Java不会自动对代码中的2进行类型转换吗?2L为何会产生不同的结果?

下面我来一步步拆解:

核心差异:字面量的类型决定了运算的基础类型

这两行代码唯一的区别就是2和2L:

  • 2是int类型字面量,而2L是long类型字面量。Java的数值运算遵循「类型提升」规则,但这个提升是按运算顺序逐步触发的,不是全局一次性转换。

第二条语句溢出的原因:中间运算全是int类型

咱们拆解2*(A.length-count1[i])*count1[i]的计算过程:

  1. A.length是int,count1[i]也是int,所以A.length-count1[i]的结果还是int。
  2. 用int类型的2去乘这个int结果,得到的依然是int值。
  3. 再和另一个int类型的count1[i]相乘——如果这几个int的乘积超过了int的最大值(2^31-1,也就是2147483647),就会发生int溢出。溢出后的值会变成错误的数值(比如负数),这时候再把这个错误值加到long类型的sum里,已经无法修正溢出带来的错误了,因为溢出已经发生在int运算的阶段。

为什么2L能避免溢出?

再看2L*(A.length-count1[i])*count1[i]的运算逻辑:

  1. 第一个运算数是long类型的2L,根据Java的类型提升规则,当long和int进行运算时,int会被自动提升为long类型。
  2. 所以A.length-count1[i]这个int结果会先被转成long,再和2L相乘,得到的是long类型的结果。
  3. 接下来和count1[i]相乘时,count1[i]也会被提升为long,整个运算过程都在long类型下进行。long的最大值是2^63-1,远大于int的上限,所以中间步骤不会发生溢出,最终得到的是正确的结果,再加到sum里自然没问题。

关于自动类型转换的误区

你可能会疑惑:sum是long类型,Java为什么不自动把整个表达式转成long?
这是因为Java的运算优先级和类型提升是逐步骤执行的,不是直接把整个表达式的结果转成目标类型。第二条语句里的所有中间运算都是int类型,溢出已经在中间步骤发生了,等结果要赋值给sum的时候,只是把错误的int值转成long,无法挽回溢出的损失。

内容的提问来源于stack exchange,提问作者RAJAT SHARMA

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:52:23