web-dev-qa-db-ja.com

Google Guava Functionインターフェースの@Nullable入力がFindBugs警告をトリガーする

_com.google.common.base.Function_インターフェイス( Google Guava から)は、applyを次のように定義します。

@Nullable T apply(@Nullable F input);

このメソッドには、次のjavadocノートがあります。

_@throws NullPointerException if {@code input} is null and this function does not accept null arguments_。

FindBugsはFunctionの私の実装について不満を言っています:

_private static final class Example implements Function<MyBean, String> {
    @Override
    @Nullable
    public String apply(@Nullable MyBean input) {
        if (null == input) {
            throw new NullPointerException();
        }
        return input.field;
    }
}
_

high-priority警告付き:

NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE、優先度:高

入力は非ヌルでなければならないが、ヌル可能としてマークされています

このパラメーターは常に非ヌルである必要がある方法で使用されますが、パラメーターは明示的にヌル可能であると注釈されています。パラメータまたは注釈の使用が間違っています。

私の関数はnull入力をサポートしていません。その場合、例外がスローされます。私が正しく理解していれば、FindBugsはこれをnull以外の要件として扱います。

私にはそれは矛盾のように見えます:入力は@Nullableですが、nullのときはメソッド@throws NullPointerExceptionです。何か不足していますか?

私が見ることができる警告を取り除く唯一の方法は手動抑制です。 (Guavaコードは明らかに私の制御の外にあります)。

@Nullableアノテーション、FindBugs、Guava、または私自身の使用について誰が間違っていますか?

35
vitaly

あなたの実装は間違っています;)

基本的にドキュメントは言う(私は言い換えて強調します):

@throws NullPointerExceptioninputがnullで、具象関数の実装がnull引数を受け入れない場合

関数を実装することにより、nullを受け入れるかどうかを決定する必要があります。最初のケースでは:

private static final class Example implements Function<MyBean, String> {
    @Override
    @Nullable
    public String apply(@Nullable MyBean input) {
        return input == null ? null : input.field;
    }
}

2番目の場合:

private static final class Example implements Function<MyBean, String> {
    @Override
    @Nullable
    public String apply(MyBean input) {
        if (null == input) {
            throw new NullPointerException();
        }
        return input.field;
    }
}

どちらの例でも、nullを返すことが許可されています。

編集:

Guavaは@javax.annotation.ParametersAreNonnullByDefaultすべてのパッケージ、したがって@Nullableが存在する場合、「グローバル@Nonnullそして、ここでnullを許可します。許可しない場合は、「ここでnullを禁止」を意味します。

そうは言っても、@Nonnull引数の注釈または@ParametersAreNonnullByDefaultパッケージ内でFindBugs関数の引数をnullにすることはできません。

編集2:

判明 このケースは既知の問題です 、コメント#3を参照してください(Guavaのリード開発者であるKevin Bourrillionから、FindbugsのリードであるBill Pughとの彼の会話について):

私の参照は、ビル・ピューとの一連の対面式の会話でした。彼は@Nullableは、一部のサブタイプmightがnullを受け入れることのみを意味します。そして、これはfindbugsによって裏付けられているようです-コードはnull可能性チェックにかなり問題なく合格しています(ただし、この特定の関数の変更が行われたため、再度チェックする必要があります)。

28
Xaerxess

パラメータのマーク@Nonnull findbugsからの問題を解決します。

3

デフォルトでは、Google Guava関数はデフォルトで@Nullableであるように見えます-注釈がなかった場合、「結果はnullではないがnull可能としてマークされている」というFindbugsエラーが発生していました。次の方法で@Nonnullを関数宣言に追加すると役立ちます。

new Function<Object, Object>() {
            @Nonnull
            public Object apply(@Nonnull Object object) {

そして今、Findbugsは幸せです。皆さんありがとう

0
Ben Thomas