背景
今天查看Sonar的时候发现静态检测出了一个bug,显示说绝对值可能为负。虽然触发的几率非常低,但是考虑到还是会存在隐患,而且一旦出问题之后可能很不容易定位,还是记录一下这个问题。具体代码如下:
int num = Math.abs(SecureRandom.getInstance("XXX").nextInt());
具体分析了一下之后,发现确实会存在当使用Integer.MIN_VALUE的时候,会造成这个问题,还是蛮有意思的,特此记录一下。
原因
我们先把结果运行一下,如下所示
System.out.println("Integer is " + Math.abs(Integer.MIN_VALUE));
System.out.println("Long is " + Math.abs(Long.MIN_VALUE));
System.out.println("Byte is " + Math.abs(Byte.MIN_VALUE));
Integer is -2147483648
Long is -9223372036854775808
Byte is 128
接着我们来看一下原因,还是在于对这个最小值的处理(或者说对负0的处理)。我们以前学过说,计算机实际处理符号数的时候,最高位是用来处理符号的,那么就可能产生一个正负零的问题,然后具体如何去处理这个就和具体的实现是有关系的(更多的还可以再回想一下反码补码之类的问题),那么在java中,具体计算过程如下图:
后记
还是一个很有意思的小问题,又再一次回顾了一些很基础的知识点。同时可以也引申复习一下到浮点类型的正负零和精度问题。
顺便吐槽一下,Random里面设计的nextInt() 和 nextInt(int xxx)两个方法,感觉应该是大概是一样的,只是后面多了一个范围限定,但是实际上正负值这个差异还挺大的,感觉有点迷惑人。
可以进一步参考的资料: