web-dev-qa-db-fra.com

L'entrée @Nullable dans l'interface de Google Guava Function déclenche l'avertissement de FindBugs

L’interface com.google.common.base.Function (de Google Guava ) définit apply comme:

@Nullable T apply(@Nullable F input); 

La méthode a la note javadoc suivante:

@throws NullPointerException if {@code input} is null and this function does not accept null arguments.

FindBugs se plaint de mon implémentation de 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;
    }
}

avec un priorité élevée warning:

NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE, priorité: élevée

l'entrée doit être non vide mais est marquée comme nullable

Ce paramètre est toujours utilisé d'une manière qui exige qu'il soit non nul, mais il est explicitement annoté comme étant Nullable. L'utilisation du paramètre ou de l'annotation est incorrecte.

Ma fonction ne prend pas en charge les entrées null et une exception est levée si tel est le cas. Si je comprends bien, FindBugs considère cela comme une exigence pour non-null.

Pour moi, cela ressemble à une contradiction: l'entrée est @Nullable mais la méthode @throws NullPointerException lorsqu'elle est nulle. Est-ce que je manque quelque chose? 

Le seul moyen de me débarrasser de l'avertissement que je peux voir est la suppression manuelle. (Le code de goyave est hors de mon contrôle, évidemment).

Qui se trompe dans l'utilisation de l'annotation @Nullable, FindBugs, Guava ou moi-même?

35
vitaly

Votre implémentation est fausse;)

Fondamentalement docs dit (je vais paraphraser et souligner):

@throws NullPointerException si input est null et la mise en oeuvre concrète de la fonction n'accepte pas les arguments nuls

En implémentant votre fonction, vous devez décider si elle accepte les valeurs NULL ou non. Dans le premier cas:

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

En second cas:

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;
    }
}

Dans les deux exemples, renvoyer null est autorisé.

EDIT:

Notez que Guava utilise @javax.annotation.ParametersAreNonnullByDefault sur tous les packages. Par conséquent, si @Nullable est présent, cela signifie "suspendre le @Nonnull global et autoriser les valeurs NULL ici", sinon, "NULL interdit ici". 

Cela dit, vous voudrez peut-être utiliser l'annotation @Nonnull sur votre argument ou @ParametersAreNonnullByDefault dans le package pour indiquer que l'argument de FindBugs ne peut pas être null.

EDIT 2:

Il s'avère que cette affaire est connue , voir le commentaire n ° 3 (de Kevin Bourrillion, développeur principal de Guava, à propos de sa conversation avec Bill Pugh, responsable de Findbugs):

Ma référence était une série de conversations en personne avec Bill Pugh. Il a affirmé sans ambiguïté que @Nullable signifie uniquement que certains sous-types Pourraient accepter null. Et cela semble être corroboré par findbugs pour nous - notre code passe assez bien les contrôles de nullabilité (bien que nous Devrions vérifier à nouveau depuis que cette fonction a été modifiée).

28
Xaerxess

Le marquage du paramètre @Nonnull résout le problème de findbugs.

3
Balamurugan Muthiah

Il semble que, par défaut, les fonctions de Google Guava soient @Nullable par défaut. Des erreurs Findbugs survenues m'indiquaient que "le résultat doit être non nul mais marqué comme nul", en l'absence d'annotation. L'ajout de @Nonnull à la déclaration de fonction de la manière suivante a aidé:

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

et maintenant Findbugs est heureux. Merci a tous

0
Ben Thomas