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

Pab*_*mez 12 java optional java-8 sonarqube 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;
}
Run Code Online (Sandbox Code Playgroud)

该方法asInteger返回Optional<Integer>

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

我理解代码是正常的,因为如果第一个是假的,那么if的第二部分将被执行.我知道这可以通过a来解决,if但我更喜欢这种方式.

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

And*_*eas 15

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

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

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

  • 甚至不需要多线程:对同一方法的两次调用不能保证返回相同的东西,我不确定Sonar是否能够保证asInteger()是幂等的. (13认同)
  • @JBNizet Sonar永远不能保证不同类中方法的任何属性,因为它甚至不能保证实现在运行时是相同的.唯一的例外是众所周知的(JDK)方法,其具有精确定义的合同或表示为注释的正式合同. (3认同)

Eug*_*ene 5

顺便说一句,您可以将其写为单个语句:

return id.asInteger()
         .map(x -> x >= BASE_ID)
         .orElse(false)
Run Code Online (Sandbox Code Playgroud)

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

  • 但是 SonarQube 无法知道对 asInteger() 的每次调用是否返回不同的值。所以第二次,当你调用 get() 时,它可能是一个空的 Optional (2认同)