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

问题描述 投票:10回答:4

我运行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>

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

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

有什么想法会发生这种情况吗?

java java-8 sonarqube optional sonarqube-scan
4个回答
14
投票

Sonarqube不能保证对id.asInteger()的两次调用返回相同的对象,例如因为多线程可能在两次调用之间改变了id的值,所以它正确地说明了存在没有经过充分测试。

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

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

4
投票

您可以将其写为单个语句btw:

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

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


0
投票

使用Optionals时,您应尽可能避免使用.isPresent.get。使用这些方法并不比使用空值更安全,并且违背了功能精神。可选项用于函数式编程和类型安全的空检查替代。

SonarQube的分析功能有限。它通常不能排除各种误报。这种情况并不是真正的问题,因为不建议以这种方式使用Optionals。


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.