Sonar 问题修复Neither “Math.abs“ nor negation should be used on numbers that could be “MIN_VALUE“

本系列主要记录分享 SonarLint 扫描出来的Bugs问题修复方案

问题

Bugs描述:Use the original value instead.
在这里插入图片描述
问题代码:

Random rand = new Random();
// 这一行是被扫描出来有问题的代码
int randInt = Math.abs(rand.nextInt());

解决办法

Random rand = new Random();
int randInt = Math.abs(rand.nextInt(Integer.MAX_VALUE));

问题分析

SonarLint 扫描结果的大概意思:代码里 Math.abs() 取绝对值后的结果,仍可能是一个负数,所以建议:

  • 使用 Random.nextLong() 去获取目标结果值;
  • 直接去掉 Math.abs() 的使用,直接取 rand.nextInt() 的值。

是不是在想为什么 Math.abs() 取到的值仍可能是一个负数呢?

这里演示一种场景:

	@Test
    public void testDemo1() {
    
    
        Integer i = Math.abs(Integer.MIN_VALUE);
        System.out.println(i);
    }

结果展示:
在这里插入图片描述
我们都知道 Integer 的取值范围:-2147483648 ~ 2147483647,所以当我们对 Integer.MIN_VALUE 去绝对值(Math.abs())操作后,得到 2147483648 就超出了 int类型的取值范围。

Oracle docs: Integer Operations中有这么一段话:

The integer operators do not indicate overflow or underflow in any way.
整数的操作不会告诉我们向上溢出还是向下溢出。
——Oracle docs

所以,溢出的结果已由语言指定,独立于JVM版本:

  • Integer.MAX_VALUE + 1 == Integer.MIN_VALUE
  • Integer.MIN_VALUE - 1 == Integer. MAX_VALUE

其他整数类型也是如此。

所以 SonarLint 才会提示我们的代码最终目标是想获取一个正值的数,当前 Math.abs(rand.nextInt()) 写法获取的结果不一定是正数。

我之前写过一篇关于:Java 边界陷阱(边界值的校验) 的博客,大家有兴趣可以瞅瞅~

我这里的解决办法是,Random 取值时指定 n 的取值范围,这样取值就不会取出负数,

ps:Random.nextInt(int n),给定一个参数n,nextInt(n)将返回一个大于等于0小于n的随机数,即:0 <= nextInt(n) < n。

参考

Sonar检测Math.abs(new Random().nextInt()) “Use the original value instead”


感 谢 各 位 大 佬 的 阅 读,随 手 点 赞,日 薪 过 万~! !!

猜你喜欢

转载自blog.csdn.net/zhuzicc/article/details/124019967
今日推荐