object == null ou null == object?

96

J'ai entendu quelqu'un qui null == objectvaut mieux que object == null vérifier

par exemple :

void m1(Object obj ) {
   if(null == obj)  // Is this better than object == null ? Why ?
       return ;
   // Else blah blah
}

Y a-t-il des raisons ou est-ce un autre mythe? Merci pour l'aide.

Jijoy
la source
Dupe de 271561 et 1957836 (sauf que celui-ci dit 'en Java')
Gishu
20
Java est différent de C #
Jijoy
5
S'il y avait un avantage significatif en
termes de
Pour les nullréférences, la marche à suivre par défaut devrait être de lancer un NPE. Certaines bibliothèques intéressantes (comme la bibliothèque Java JDK7) ont une méthode quelque chose comme public static <T> T notNull(T obj) { if (obj == null) { throw new NullPointerException(); } else { return obj; } }. Il y a aussi @NonNull(ou @Nonnull?), Mais cela est "effacé".
Tom Hawtin - tackline
2
null == objectest connue comme une condition Yoda .
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Réponses:

140

C'est probablement une habitude apprise de C, pour éviter ce genre de faute de frappe (simple =au lieu d'un double ==):

if (object = null) {

La convention consistant à placer la constante sur le côté gauche de ==n'est pas vraiment utile en Java car Java nécessite que l'expression dans un ifévalue à une booleanvaleur, donc à moins que la constante ne soit a boolean, vous obtiendriez une erreur de compilation de toute façon arguments. (et si c'est un booléen, vous ne devriez pas utiliser de ==toute façon ...)

Laurence Gonsalves
la source
4
ce qui n'est pas une habitude très utile pour java, car la faute de frappe entraînerait une erreur de compilation sur java
radai
11
Sauf dans un cas d'angle spécifique. stackoverflow.com/questions/2369226/null-check-in-java/…
Chandra Sekar
3
@Chandru pour un booléen, vous pouvez utiliser x.booleanValue()ou !x.booleanValue(). x == trueou x == falsedans une expression de condition est une mauvaise odeur, à mon humble avis.
Laurence Gonsalves
2
Il recherche null ici. Et il y a des cas où il doit vraiment vérifier un booléen pour null car null n'est ni vrai ni faux.
Chandra Sekar
1
S'habituer à utiliser null == objectjuste pour s'assurer que nous n'écrasons pas accidentellement un objet avec une faute de frappe ne devrait pas du tout être un cas d'utilisation. Ce qui veut dire que, nous nous entraînons à ce que maintenant que j'utilise d'abord "null", ça va, même si je fais une erreur. Cela ne signifie pas que le code fonctionne comme prévu. Même s'il null = objectest donné à la place de null == object, le programme ne fonctionnera pas comme prévu! Alors ça ne sert à rien de suivre cette convention!
VanagaS
32

Comme d'autres l'ont dit, c'est une habitude apprise de C pour éviter les fautes de frappe - même si même en C, je m'attendrais à des compilateurs décents à des niveaux d'avertissement suffisamment élevés pour donner un avertissement. Comme le dit Chandru, comparer avec null en Java de cette manière ne poserait des problèmes que si vous utilisiez une variable de type Boolean(que vous n'êtes pas dans l'exemple de code). Je dirais que c'est une situation assez rare, et pas une pour laquelle il vaut la peine de changer la façon dont vous écrivez du code partout ailleurs. (Je ne prendrais pas la peine d'inverser les opérandes même dans ce cas; si je réfléchis suffisamment clairement pour envisager de les inverser, je suis sûr que je peux compter les signes égaux.)

Ce qui n'a pas été mentionné, c'est que beaucoup de gens (moi y compris certainement) trouvent que le if (variable == constant)formulaire est plus lisible - c'est une façon plus naturelle de s'exprimer. C'est une raison pour ne pas copier aveuglément une convention de C. Vous devriez toujours remettre en question les pratiques (comme vous le faites ici :) avant de supposer que ce qui peut être utile dans un environnement l'est dans un autre.

Jon Skeet
la source
3
J'accepte chaque mot que vous avez dit, en particulier la partie "copier aveuglément une convention". Je lis un code en ce moment et le style null = object m'ennuie tellement que je le cherche et je suis venu ici. À quoi pensait le codeur?
Adrian M
28

Cela n'a pas beaucoup de valeur en Java (1.5+) sauf lorsque le type d'objet l'est Boolean. Dans ce cas, cela peut toujours être pratique.

if (object = null)n'entraînera pas d'échec de compilation dans Java 1.5+ si l'objet est Booleanmais lèverait un NullPointerExceptionà l'exécution.

Chandra Sekar
la source
Vous
vouliez
7
Non, cela ne provoquera pas d'erreur de compilation lorsque l'objet est booléen.
Chandra Sekar
N'est-ce pas la même chose pour chaque type d'objet en plus de Boolean?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
2
Pour les types non booléens, le code ne sera pas compilé car le type de l'expression "object = null" ne sera pas booléen. En raison de l'auto-boxing, il se compilera pour Boolean.
Chandra Sekar
Mais pourquoi ce comportement pour Boolean? Une justification?
Rohit Banga
9

En Java, il n'y a pas de bonne raison.

Quelques autres réponses ont affirmé que c'est parce que vous pouvez accidentellement en faire une affectation au lieu de l'égalité. Mais en Java, vous devez avoir un booléen dans un if, donc ceci:

if (o = null)

ne compilera pas.

Le seul moment où cela pourrait avoir une importance en Java est si la variable est booléenne:

int m1(boolean x)
{
    if (x = true)  // oops, assignment instead of equality
R Samuel Klatchko
la source
4
Mais pourquoi écririez-vous jamais == trueou également == true == true.
Tom Hawtin - Tacle du
7
Il n'y a pas de bonne raison d'écrire == true. Mais j'ai vu tellement de mauvais codes dans ma carrière que je ne demande plus pourquoi quelqu'un écrirait quelque chose et accepterait simplement que certaines personnes aient écrit du code inutile / discutable.
R Samuel Klatchko
1
En effet, il y a beaucoup de mauvais code qui volent, quand même, quand on le considère x == truecomme mauvais parce qu'il pourrait être écrit par erreur x = true, il n'y aurait pas beaucoup de sens à le changer en true == xplutôt que simplement x.
Holger
9

Ceci est également étroitement lié à:

if ("foo".equals(bar)) {

ce qui est pratique si vous ne voulez pas traiter avec des NPE:

if (bar!=null && bar.equals("foo")) {
cherouvim
la source
peut être pratique mais peut être dangereux blue-walrus.com/2010/11/…
Oliver Watkins
@OliverWatkins: Je trouve cet article faible. Supposons que la variable soit de type int. Si elle n'est pas initialisée, la valeur serait 0 et la promesse de l'article ne tiendrait pas. Le fait que les chaînes soient des objets et que les ints soient des primitives n'est pas pertinent du fait qu'un programmeur peut oublier d'initialiser une variable. Dans cette question, nous résolvons simplement la chose de comparaison de chaîne nulle.
cherouvim
@cherouvim le fait qu'il s'agisse d' intun type primitif est pertinent, car il est impossible d'invoquer equalssur un int, par conséquent, il est inutile de discuter de l'utilisation x.equals(constant)ou constant.equals(x)des intvaleurs. Et pour les Integervaleurs, la valeur par défaut est nullplutôt que 0.
Holger
5

Cette astuce est censée éviter les v = nulltypes de fautes de frappe.

Mais Java n'autorise que les expressions booléennes comme if()conditions de sorte que cette astuce n'a pas beaucoup de sens, le compilateur trouvera quand même ces fautes de frappe.

C'est toujours une astuce précieuse pour le code C / C ++.

vava
la source
3

Pour la même raison, vous le faites en C; affectation est une expression, vous mettez donc le littéral à gauche pour ne pas pouvoir l'écraser si vous l'utilisez accidentellement à la =place de ==.

Ignacio Vazquez-Abrams
la source
Ce n'est un problème en Java que pour les types booléens, non? Tout autre type d'affectation n'aura pas de type booléen et devrait provoquer une erreur du compilateur.
Scott Smith
1
non, le compilateur Java attrapera ce genre de faute de frappe quel que soit l'ordre que vous préférez
vava
@Jijoy - Je ne pense pas que cela ait quoi que ce soit à voir avec les performances. Cela ressemble à une vieille astuce en C pour éviter la terrible erreur d'assignation dans une expression conditionnelle. L'idée était que si vous essayez de vérifier si xégal à égal 5, lorsque vous tapez par erreur if (x = 5), il se compilera silencieusement (et évaluera toujours true, quelle que soit la valeur de x). Cependant, si vous prenez l'habitude de toujours spécifier d'abord le littéral: 'if (5 = x)', le compilateur peut vérifier votre travail et vous faire gagner du temps dans le débogueur. Les compilateurs modernes rendent cette habitude inutile.
Scott Smith
6
-1: Si vous utilisez accidentellement = il ne se compilera pas en Java; donc la raison de C ne s'applique pas.
Jon Skeet
Techniquement, si objc'était de type java.lang.Boolean(gros B), alors ça pourrait faire une différence (je pense, pas vraiment essayé ou quoi que ce soit).
Tom Hawtin - Tacle du
3

C'est pour les personnes qui préfèrent avoir la constante sur le côté gauche. Dans la plupart des cas, avoir la constante sur le côté gauche empêchera NullPointerException d'être levée (ou d'avoir un autre contrôle nul). Par exemple, la méthode String equals effectue également une vérification nulle. Avoir la constante à gauche vous empêchera d'écrire le chèque supplémentaire. Ce qui, d'une autre manière, est également effectué plus tard. Avoir la valeur nulle sur la gauche est juste cohérent.

comme:

 String b = null;
 "constant".equals(b);  // result to false
 b.equals("constant");  // NullPointerException
 b != null && b.equals("constant");  // result to false
SPee
la source
cette dissimulation de NPE crée encore plus de bogues plus difficiles à trouver plus en aval
Oliver Watkins
2

C'est la condition Yoda qui écrit de manière différente

En java

String myString = null;
if (myString.equals("foobar")) { /* ... */ } //Will give u null pointer

état de Yoda

String myString = null;
if ("foobar".equals(myString)) { /* ... */ } // will be false 
Tanmay Naik
la source
1

Comparez avec le code suivant:

    String pingResult = "asd";
    long s = System.nanoTime ( );
    if ( null != pingResult )
    {
        System.out.println ( "null != pingResult" );
    }
    long e = System.nanoTime ( );
    System.out.println ( e - s );

    long s1 = System.nanoTime ( );
    if ( pingResult != null )
    {
        System.out.println ( "pingResult != null" );
    }
    long e1 = System.nanoTime ( );
    System.out.println ( e1 - s1 );

Sortie (après plusieurs exécutions):

null != pingResult
325737
pingResult != null
47027

Par conséquent, pingResult != nullest le gagnant.

Avinash
la source
7
Exécutez votre test dans une boucle supplémentaire! Ou changez simplement les instructions IF. Bref, il n'y a pas de différence! La première boucle est toujours plus lente.
Marcel Jaeschke
Dans ce test, pingResult est toujours non nul. Qu'arrive-t-il au moment où pingResult est nul? Je parie que c'est indépendant de la plate-forme, mais sur ma pile Oracle Java 1.6 / Linux, les résultats sont à peu près égaux (en boucle), sauf si pingResult est nul, les deux vérifications sont quelques pour cent plus rapides.
Ogre Psalm33
1
si vous mettez "pingResult! = null block avant null! = pingResult block, il en résultera quelque chose comme" pingResult! = null 325737 "
Sola Yang
Comme le dit @Sola Yang, si vous mettez pingResult! = Null avant, vous verrez que cela prend plus de temps que null! = PingResult. Si pingResult! = Null était plus rapide que null! = PingResult l'EDI (comme IntelliG, Eclipse, ...) fera un avertissement pour forcer les développeurs à utiliser ce rôle;)
adil.hilmi
1

En raison de sa propriété commutative , la seule différence entre object == nullet null == object(la version Yoda ) est de nature cognitive : comment le code est lu et digéré par le lecteur. Je ne connais pas la réponse définitive, mais je sais que je préfère personnellement comparer l'objet que j'inspecte à autre chose, plutôt que de comparer autre chose à l'objet que j'inspecte , si cela a un sens. Commencez par le sujet, puis la valeur à laquelle le comparer.

Dans certaines autres langues, ce style de comparaison est plus utile.

Pour se prémunir contre un signe "=" manquant en général, je pense que l'écriture null == objectest un acte malavisé de programmation défensive . La meilleure façon de contourner ce code particulier est de garantir le comportement avec un test junit. N'oubliez pas que l'erreur possible de manquer un "=" ne dépend pas des arguments d'entrée de la méthode - vous n'êtes pas dépendant de la bonne utilisation de cette API par d'autres personnes - donc un test junit est parfait pour se prémunir contre cela. Quoi qu'il en soit, vous voudrez écrire des tests junit pour vérifier le comportement; un "=" manquant entre naturellement dans le champ d'application.

Benny Bottema
la source