web-dev-qa-db-ja.com

単一行でOptional#isPresent()を呼び出すと、呼び出されないと報告されます

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の2番目の部分は、最初の部分がfalseの場合は実行されないため、コードに問題がないことを理解しています。これは.filter(..).isPresent()で解決できることは知っていますが、この方法の方が好きです。

なぜこれが起こるのでしょうか?

14

Sonarqubeは、id.asInteger()への2回の呼び出しが同じオブジェクトを返すことを保証できません。マルチスレッドによって2つの呼び出し間でidの値が変更された可能性があるため、プレゼンスが適切にテストされていないことを正しく示しています。

isPresent()get()が同じオブジェクトで呼び出されるように、最初にローカル変数に割り当てるコードを変更します。

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

あなたはそれを単一のステートメントとして書くことができますところで:

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

しかし、ソナーの不満は、この場合は誤検知であるためです。

4
Eugene

この問題を回避するために、iterator()。next()を使用します。これは、.getと同じ機能を備えていますが、isPresent()の問題はありません。

0
Leandro Maro

オプションを使用する場合は、.isPresent.getをできるだけ避ける必要があります。これらのメソッドの使用は、nullを使用するよりも安全ではなく、機能的な精神に反します。関数型プログラミングおよびnullチェックのタイプセーフな代替手段のためにオプションが作成されています。

SonarQubeの分析機能は限られています。通常、すべての種類の誤検知を除外することはできません。この方法でオプションを使用することは推奨されないため、このケースは実際には問題ではありません。

0
Donat