Java 在单行中调用可选的#isPresent()会报告为未调用

Java 在单行中调用可选的#isPresent()会报告为未调用,java,java-8,sonarqube,optional,sonarqube-scan,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 我从sonarqube得到的

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

我从sonarqube得到的错误是
在访问值之前调用“Optional#isPresent()”。
在回程线上

我理解代码是可以的,因为如果第一部分为false,则不会执行
if
的第二部分。我知道这可以通过
.filter(..).isPresent()解决,但我更喜欢这种方式


你知道为什么会这样吗?

你可以把它写成一句话,顺便说一句:

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

但声纳的抱怨是因为在这种情况下它是假阳性

Sonarqube不能保证对
id.asInteger()
的两个调用返回相同的对象,例如,因为多线程可能在两个调用之间更改了
id
的值,因此正确地说明存在性未经充分测试

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

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

使用Optionals时,应尽量避免使用
。i呈现
。获取
。在中使用这些方法并不比使用null更安全,并且违背了函数精神。选项用于函数编程和空检查的类型安全替代


SonarQube的分析能力有限。它通常不能排除所有类型的假阳性。这种情况实际上不是问题,因为不建议以这种方式使用Optionals

为了避免这个问题,我使用了迭代器().next()它的功能与.get相同,但是它没有isPresent()问题

我认为这只是因为那些代码检查工具并不总是完美地工作,有些错误只是误报。如果您将其重写为
IF(…)
,我确信不会再报告错误。如果第二次调用
id.asInteger()
将返回空
可选
?那么
返回id.asInteger().orElse(-1)>=BASE\u id?是的,我知道我可以用不同的方法解决它,就像我在问题本身中写的:
.filter(..).isPresent()
但我更喜欢另一种方法,我想了解为什么会发生这种情况。我的意思是,正在调用isPresent(),但SonarQube不知道是否每次调用asInteger()都返回不同的值。因此,第二次,当您调用get()时,它可能是一个空选项这不是一个假阳性-Sonar强调这一点是完全正确的,因为一个潜在的问题Multi-threading甚至不需要:对同一个方法的两个调用不能保证返回相同的内容,我不确定Sonar是否能够保证asInteger()的正确性“是幂等的。”Andreas说得很好,1+,但我会把它完全写成一条语句though@JBNizetSonar永远不能保证不同类中方法的任何属性,因为它甚至不能保证在运行时实现是相同的。唯一的例外是具有精确定义的契约或以注释形式表示的正式契约的众所周知(JDK)方法。例如,如果您想在值不存在的情况下执行某些操作,您将如何不使用
isPresent
。@tsolakp因为Java 9
yourOptional.ifpresentorese(dummy,this::someAction)。不过,你的观点是正确的,这是一种罕见的(甚至可能是受欢迎的)情况,人们可以为使用
isPresent()
进行辩护。是的,我的意图不是说“你不能使用isPresent”,而是“在大多数情况下,如果可能的话,最好避免使用它”。