35 votes

Google-guava checkNotNull et IntelliJ IDEA "may produce java.lang.NullPointerException" (peut produire une exception)

Existe-t-il un moyen de supprimer cet avertissement ?

MyClass object = null;

/*Some code that 'might' set this object but I know it will*/      

Preconditions.checkNotNull(object); 
//when "assert object != null" is used here no warning is shown

merged.setName(dRElement.getName());
//"May produce 'java.lang.NullPointerException'" warning here 

J'utilise IntelliJ IDEA 10.5 et je sais que cet avertissement n'est pas nécessaire, mais je voudrais le supprimer juste ici et éviter de désactiver les inspections.

32voto

Mark Peters Points 42201

Grâce à une combinaison de @Contract et de la fonction Annotations externes, vous pouvez désormais annoter Preconditions de sorte qu'IntelliJ applique l'analyse statique correcte aux appels à ces méthodes.

Disons que nous avons cet exemple

public void doSomething(Object someArg) {
    Preconditions.checkArgument(someArg != null);
    someArg.doSomethingElse();  //currently gives NPE warning

    if (someArg != null) {
        //no warning that this is always true
    }
}

Dans IntelliJ (j'utilise la version 13) :

  • Naviguez vers Preconditions.checkArgument(boolean) .
  • Placez votre curseur sur le nom de la méthode, et appuyez sur Alt - Enter pour faire apparaître la fenêtre popup des intentions.
  • Sélectionnez "Ajouter un contrat de méthode".
  • Utiliser le texte du contrat false -> fail .
  • Lorsque vous y êtes invité, indiquez un emplacement pour le fichier d'annotations externes.

Maintenant, l'avertissement à someArg.doSomethingElse() disparaît, et IDEA va, en fait, signaler l' if branche comme toujours vrai !

Autres textes contractuels :

  • Preconditions.checkArgument(boolean, String) devrait être false, _ -> fail
  • Preconditions.checkNotNull(Object, String) devrait être null, _ -> fail ,
  • etc, etc.

Voici l'intégralité de mon annotations.xml pour Preconditions :

<root>
    <item name='com.google.common.base.Preconditions T checkNotNull(T)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;null -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions T checkNotNull(T, java.lang.Object)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;null, _ -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions T checkNotNull(T, java.lang.String, java.lang.Object...)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;null, _, _ -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions void checkArgument(boolean)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;false -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions void checkArgument(boolean, java.lang.Object)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;false, _ -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions void checkArgument(boolean, java.lang.String, java.lang.Object...)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;false, _, _ -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions void checkState(boolean)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;false -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions void checkState(boolean, java.lang.Object)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;false, _ -&gt; fail&quot;"/>
        </annotation>
    </item>
    <item name='com.google.common.base.Preconditions void checkState(boolean, java.lang.String, java.lang.Object...)'>
        <annotation name='org.jetbrains.annotations.Contract'>
            <val val="&quot;false, _, _ -&gt; fail&quot;"/>
        </annotation>
    </item>
</root>

Voir aussi

15voto

Johnny Points 447

Un site un vieux problème existe dans JetBrains Yourtrack pour ajouter ce type de fonctionnalité. J'ai voté pour il y a des années, mais je ne vois pas d'activité. Si tout le monde vote pour, nous aurons peut-être de la chance.

Pour clarifier le problème, il faut ajouter une fonctionnalité permettant de marquer une méthode comme effectuant un certain type de contrôle des nullités. Dans ce cas, vous pourriez écrire votre propre enveloppe pour la méthode Preconditions et l'annoter.

UPDATE J'en ai eu assez d'attendre cette fonctionnalité et j'ai donc soumis moi-même un patch. Il est disponible dans la version 12.1.1 build 129.239. Pour accéder à la configuration : Paramètres > Inspections > Bogues probables > Conditions constantes et exceptions > Configurer les méthodes Assert/Check.

2voto

Kurt Points 21

Extraire une méthode ?

private MyClass getMyClass() {
    /* This always returns an instance of MyClass, never null. */      
}

...

MyClass object = getMyClass();
Preconditions.checkNotNull(object);
merged.setName(object.getName());

1voto

milhauz Points 21

Vous pouvez également attribuer la valeur retournée par la méthode checkNotNull, qui est non nulle : http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/base/Preconditions.html#checkNotNull(T)

MyClass object = null;
object = Preconditions.checkNotNull(object); 
merged.setName(dRElement.getName());

0voto

Premraj Points 2931

En dehors des autres options, vous pouvez essayer

Supprimez les avertissements au niveau de la méthode en utilisant -

@SuppressWarnings({"NullableProblems"})
public void someMethod(){
   ...
   ...
}

ou supprimer l'avertissement au niveau de l'énoncé en utilisant le commentaire -.

//noinspection NullableProblems
someMethodCallProducingNullWarning(null);

Mais avant de faire cela, assurez-vous que cela ne produit pas vraiment un NPE.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X