Java: comment vérifier si l'objet est nul?

87

Je crée une application qui récupère des images sur le Web. Si l'image ne peut pas être récupérée, une autre image locale doit être utilisée.

En essayant d'exécuter les lignes suivantes:

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable.equals(null)) {
  drawable = getRandomDrawable();
}

La ligne if (drawable.equals (null)) lève une exception si drawable est null.

Est-ce que quelqu'un sait comment vérifier la valeur de drawable pour ne pas lever d'exception au cas où elle serait nulle et récupérer l'image locale (exécutez drawable = getRandomDrawable ())?

Niko Gamulin
la source
23
Utilisez if (drawable == null) L' appel d'une méthode sur un objet NULL est une exception NullPointerException.
décédé le
3
Pourquoi n'écrivez-vous pas une réponse habituelle au lieu d'un commentaire, diciu?
démon le
@JaredBurrows Ne modifiez pas le code d'une question d'une manière qui va à l'encontre du but de la question!
Gilles 'SO- arrête d'être diabolique'
@Gilles Lisez mon commentaire éditorial, j'ai rendu le code plus lisible.
Jared Burrows
@JaredBurrows Non, votre modification n'était pas un changement de «formatage». Vous avez changé le code non fonctionnel qui était l'objet de la question, en code fonctionnel qui a rendu la question discutable.
Gilles 'SO- arrête d'être diabolique'

Réponses:

35

Solution Java 8 modifiée:

final Drawable drawable = 
    Optional.ofNullable(Common.getDrawableFromUrl(this, product.getMapPath()))
        .orElseGet(() -> getRandomDrawable());

Vous pouvez déclarer drawable finaldans ce cas.

Comme l'a souligné Chasmo, Android ne prend pas en charge Java 8 pour le moment. Cette solution n'est donc possible que dans d'autres contextes.

démon
la source
7
Probablement pas une bonne idée - vous revenez à Fortran 60 où les deux côtés du conditionnel sont évalués, puis un seul est utilisé. C'est mauvais si la branche inutilisée a un calcul, ce qui est vrai la plupart du temps, donc ce n'est pas une méthode généralement utile. Je déplacerais la condition vers la Commonclasse, et vous permettrais de fournir une URL de secours et de garder les responsabilités ensemble.
Pete Kirkham le
1
L'exemple est maintenant complètement réécrit en Java 8, donc ma solution ne souffre plus d'évaluations inutiles (comme l'a souligné @PeteKirkham dans ma solution d'origine).
démon du
1
Android ne prend pas en charge Java 8. Il ne prend en charge que Java 7 (si vous avez kitkat) et n'a toujours pas invokedynamic, seulement le nouveau sucre de syntaxe. À côté de cela, cela Optional.ofimplique que la valeur n'est pas nulle et que, par conséquent, le orElseGetn'est pas nécessaire. Vous devriez utiliser Optional.ofNullabledans ce cas.
Martin Seeler
179
Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable == null) {
    drawable = getRandomDrawable();
}

La equals()méthode vérifie l' égalité des valeurs , ce qui signifie qu'elle compare le contenu de deux objets. Puisque ce nulln'est pas un objet, cela se bloque lorsque vous essayez de comparer le contenu de votre objet avec le contenu de null.

L' ==opérateur vérifie l' égalité des références , ce qui signifie qu'il regarde si les deux objets sont réellement le même objet . Cela ne nécessite pas que les objets existent réellement; deux objets ( nullréférences) inexistants sont également égaux.

Thomas
la source
56
Je veux ajouter un conseil très précieux: si vous avez des chaînes ou des constantes à comparer, placez-les toujours en premier dans la clause equals. (if ("coyote" .equals (myDogString))) est bien meilleur que (if (myDogString.equals ("coyote"))) car dans le second cas myDogString peut être nul et lance un NPE alors que dans le premier cas il ne le fait pas peu importe si myDogString est nul.
Thorsten S.
20
Connu comme une condition de Yoda: "si un coyote, le chien est ..."
Thomas
1
Je voudrais également ajouter que depuis Java 7, il existe une méthode Objects.equals (), qui ne vous soucie pas de la syntaxe Yoda
maryokhin
21

J'utilise cette approche:

if (null == drawable) {
  //do stuff
} else {
  //other things
}

De cette façon, je trouve améliore la lisibilité de la ligne - car je lis rapidement un fichier source, je peux voir que c'est une vérification nulle.

En ce qui concerne la raison pour laquelle vous ne pouvez pas appeler .equals()un objet qui peut être null; si la référence d'objet que vous avez (à savoir 'drawable') est en fait null, elle ne pointe pas vers un objet sur le tas. Cela signifie qu'il n'y a pas d'objet sur le tas sur lequel l'appel à equals()peut réussir.

Bonne chance!

hors du café
la source
4
Moi aussi, je préfère la construction if (<constant> == <variable>) comme moyen de me protéger d'une affectation accidentelle.
Scott le
8

DIY

private boolean isNull(Object obj) {
    return obj == null;
}

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (isNull(drawable)) {
    drawable = getRandomDrawable();
}
Eddie B
la source
6
drawable.equals(null)

La ligne ci-dessus appelle la méthode "equals (...)" sur l'objet dessinable.

Ainsi, lorsque drawable n'est pas nul et qu'il s'agit d'un objet réel, alors tout se passe bien et l'appel de la méthode "equals (null)" retournera "false"

Mais quand "drawable" est nul, cela signifie appeler la méthode "equals (...)" sur un objet nul, signifie appeler une méthode sur un objet qui n'existe pas donc il lève "NullPointerException"

Pour vérifier si un objet existe et qu'il n'est pas nul, utilisez ce qui suit

if(drawable == null) {
    ...
    ...
}

Dans la condition ci-dessus, nous vérifions que la variable de référence "drawable" est nulle ou contient une valeur (référence à son objet) afin qu'elle ne lève pas d'exception dans le cas où drawable est nul comme vérification

null == null

est valable.

Yatendra Goel
la source
5

if (yourObject instanceof yourClassName)évaluera falsesi yourObjectest null.

utilisateur de tas
la source
0

Il est probablement légèrement plus efficace d'attraper une NullPointerException. Les méthodes ci-dessus signifient que le moteur d'exécution vérifie deux fois les pointeurs nuls.

Tom R
la source
1
Où est la if x == nullsolution de double enregistrement ?
démon le
Après l'instruction if, le moteur d'exécution vérifiera à nouveau la présence d'un pointeur nul lorsque l'objet est utilisé. Je ne sais pas si cela est optimisé par le compilateur ou non.
Tom R
4
Cela va à l'encontre de la sagesse conventionnelle, en utilisant des exceptions comme flux de contrôle.
James
1
Les exceptions sont très coûteuses, car elles doivent créer un stacktrace complet.
démon du
0

Utilisez les librairies google guava pour gérer is-null-check (mise à jour de Deamon)

Drawable drawable = Optional.of(Common.getDrawableFromUrl(this, product.getMapPath())).or(getRandomDrawable());
Bala
la source
Mieux vaut utiliser Java 8 Optionalaujourd'hui.
démon du
-1

Juste pour donner quelques idées au développeur de source Java d'Oracle :-)

La solution existe déjà en .Net et est de plus en plus lisible!

Dans Visual Basic .Net

Drawable drawable 
    = If(Common.getDrawableFromUrl(this, product.getMapPath())
        ,getRandomDrawable()
        )

En C #

Drawable drawable 
    = Common.getDrawableFromUrl(this, product.getMapPath() 
        ?? getRandomDrawable();

Ces solutions sont puissantes en tant que solution Java facultative (la chaîne par défaut n'est évaluée que si la valeur d'origine est nulle) sans utiliser l'expression lambda, simplement en ajoutant un nouvel opérateur.

Juste pour voir rapidement la différence avec la solution Java, j'ai ajouté les 2 solutions Java

Utilisation facultative en Java

Drawable drawable = 
    Optional.ofNullable(Common.getDrawableFromUrl(this, product.getMapPath()))
        .orElseGet(() -> getRandomDrawable());

Utilisation de {} en Java

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable != null)
    {
    drawable = getRandomDrawable();
    }

Personnellement, j'aime VB.Net mais je préfère ?? C#ou if {}solution en Java ... et vous?

schlebe
la source