在单行中调用Optional#isPresent()报告为未调用

时间:2018-11-06 20:37:53

标签: java java-8 sonarqube optional sonarqube-scan

我运行SonarQube检查我的代码,发现一个我不理解所报告错误的情况。

我的代码是:

private static final int BASE_ID = 100_000_000;
private boolean isValidId(Id id) {
    return id.asInteger().isPresent() && id.asInteger().get() >= BASE_ID;
}

方法asInteger返回Optional<Integer>

我从声纳库得到的错误是 Call "Optional#isPresent()" before accessing the value. 在返回行中。

我了解该代码是可以的,因为如果if的第二部分为假,则第二部分将不会执行。我知道可以用.filter(..).isPresent()来解决,但我更喜欢这种方式。

任何想法为什么会发生这种情况?

4 个答案:

答案 0 :(得分:13)

Sonarqube无法保证对id.asInteger()的两次调用返回相同的对象,例如因为多线程可能已更改了两次调用之间的id的值,所以正确地指出存在性尚未得到充分测试。

更改代码以首先分配给局部变量,以确保在同一对象上调用isPresent()get()

private boolean isValidId(Id id) {
    Optional<Integer> idAsInteger = id.asInteger();
    return idAsInteger.isPresent() && idAsInteger.get() >= BASE_ID;
}

答案 1 :(得分:4)

您可以将其写为一个单独的语句:

return id.asInteger()
         .map(x -> x >= BASE_ID)
         .orElse(false)

但是声纳抱怨是因为在这种情况下它是一个误报。

答案 2 :(得分:0)

使用Optionals时,应尽量避免使用.isPresent.get。使用这些方法并不比使用null更安全,并且违反了功能精神。为函数编程和null检查的类型安全替代方法提供了可选选项。

SonarQube的分析功能有限。它通常不能排除各种误报。这种情况实际上不是问题,因为不建议这样使用Optionals。

答案 3 :(得分:0)

为避免此问题,我使用iterator()。next(),它具有与.get相同的功能,但它没有isPresent()问题!