一次 java/scala 整型溢出的问题

2020/09/01 Java

一次 Java/Scala 整型溢出的问题

刚到新公司,为了测试一下内部的 git 权限,就随便修改了一点代码,提交一下,看是否可以正常提交代码。

本来想修改的都是没有什么影响的代码,结果第一次提交代码就出现了问题。。。

记录一下,引以为戒。

原来的代码是这样的:

private val readLimit = 21990232555520L

修改后为:

private val readLimit = 20 * 1024 * 1024 * 1024 * 1024L

表示读限制为 20TB

谁知道竟然出现了问题,你们猜是什么问题???

~我是分隔符~







可能有些人已经发现了,发生了整型溢出导致readLimit 为负数,险些踉成大错。。。

20 * 1024 * 1024 *1024 = 21474836480
//Java 中int 最大值为:Integer.MAX_VALUE = 2147483647

显然 20 * 1024 * 1024 *1024 > Integer.MAX_VALUE,最终导致整型溢出。

说实话这个错误发生的对我来说并不是偶然,如果这次不出现,可能以后我还是会犯类似的,这里面有一个思维定势。

虽然整型溢出和范围我一直都是有概念的,比如写类似如下代码的时候,我会非常小心和注意。

int readLimit = 20*1024*1024*1024;//错误,溢出

但是假如写如下代码:

long readLimit = 20 * 1024 * 1024 * 1024 * 1024L

没有想到这块会整型溢出,误以为会自动类型推导的,因为后面特意写了 *1024L 来表示这个一个 long 类型。

这块也是我的一个思维定势,比如 HBase 源代码 中,默认的 Region Size 最大值的代码 :

public static final long DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024 * 1024L;

当然如上代码是没有问题的,因为 10*1024*1024 并没有超过整型的最大值,但是这种写法是不值得推荐的。

其实这个问题,细想想的话,Java 操作符优先级的话,应该是可以发现的,但还是发生了一个思维定势想当然的低级错误。

最后推荐一下比较好的写法是

long readLimit = 20L * 1024L * 1024L * 1024L * 1024L
或者
long readLimit = 20L * 1024 * 1024 * 1024 * 1024

也就是先把 long 类型放在前面即可。

非常不推荐如下写法

long readLimit = x*y*z*1024L

即使当时不发生溢出,也有可能因为参数,或者调整了xyz的大小导致溢出

Search

    Post Directory