Objekt == null oder null == Objekt?


95

Ich habe von jemandem null == objectgehört, der besser ist als zu object == null überprüfen

z.B :

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

Gibt es Gründe oder ist dies ein anderer Mythos? Danke für die Hilfe.


Dupe von 271561 und 1957836 (außer dass dieser 'in Java' sagt)
Gishu

20
Java unterscheidet sich von C #
Jijoy

5
Wenn es war ein deutlichen Leistungsvorteil, dann sicher , dass der Compiler optimieren würde ...
Andreas Dolk

Für nullReferenzen sollte die Standardmaßnahme darin bestehen, eine NPE zu werfen. Einige nette Bibliotheken (wie die JDK7-Java-Bibliothek) haben eine Methode wie public static <T> T notNull(T obj) { if (obj == null) { throw new NullPointerException(); } else { return obj; } }. Es gibt auch @NonNull(oder @Nonnull?), Aber das wird "gelöscht".
Tom Hawtin - Tackline

Antworten:


139

Dies ist wahrscheinlich eine Gewohnheit, die von C gelernt wurde, um diese Art von Tippfehler zu vermeiden (einfach =statt doppelt ==):

if (object = null) {

Die Konvention, die Konstante auf die linke Seite von zu setzen, ==ist in Java nicht wirklich nützlich, da Java erfordert, dass der Ausdruck in einer ifAuswertung einen booleanWert ergibt. Wenn die Konstante also nicht a ist boolean, wird in beiden Fällen ein Kompilierungsfehler angezeigt Argumente. (und wenn es ein Boolescher Wert ist, sollten Sie ihn ==sowieso nicht verwenden ...)


4
Das ist keine sehr nützliche Angewohnheit für Java, da der Tippfehler zu einem Kompilierungsfehler auf Java führen würde
Radai


3
@Chandru für einen Booleschen Wert können Sie x.booleanValue()oder verwenden !x.booleanValue(). x == trueoder x == falsein einem Zustand Ausdruck ist ein schlechter Geruch, IMHO.
Laurence Gonsalves

2
Er sucht hier nach Null. Und es gibt Fälle, in denen er einen Booleschen Wert wirklich auf null prüfen muss, da null weder wahr noch falsch ist.
Chandra Sekar

1
Sich daran zu gewöhnen, null == objectnur um sicherzustellen, dass wir Objekte nicht versehentlich mit einem Tippfehler überschreiben, sollte überhaupt kein Anwendungsfall sein. Das heißt, wir trainieren uns selbst, dass es jetzt, wo ich zuerst "null" benutze, in Ordnung ist, auch wenn ich einen Fehler mache. Das bedeutet nicht, dass der Code wie erwartet funktioniert. Selbst wenn null = objectanstelle von angegeben null == object, wird das Programm nicht wie erwartet funktionieren! Dann macht es keinen Sinn, dieser Konvention zu folgen!
VanagaS

32

Wie andere gesagt haben, ist es eine Gewohnheit von C, Tippfehler zu vermeiden - obwohl ich selbst in C anständige Compiler mit ausreichend hohen Warnstufen erwarten würde, um eine Warnung zu geben. Wie Chandru sagt, würde ein Vergleich mit null auf Java auf diese Weise nur dann Probleme verursachen, wenn Sie eine Variable vom Typ verwenden Boolean(die nicht im Beispielcode enthalten ist). Ich würde sagen, das ist eine ziemlich seltene Situation und keine, für die es sich lohnt, die Art und Weise zu ändern, wie Sie überall Code schreiben. (Ich würde mich auch in diesem Fall nicht darum kümmern, die Operanden umzukehren. Wenn ich klar genug denke, um sie umzukehren, kann ich sicher die Gleichheitszeichen zählen.)

Was nicht erwähnt wurde, ist, dass viele Leute (ich selbst sicherlich eingeschlossen) das if (variable == constant)Formular besser lesbar finden - es ist eine natürlichere Art, sich auszudrücken. Dies ist ein Grund , eine Konvention nicht blind aus C zu kopieren. Sie sollten Praktiken immer in Frage stellen (wie Sie es hier tun :), bevor Sie davon ausgehen, dass das, was in einer Umgebung nützlich sein kann, in einer anderen nützlich ist.


3
Ich stimme jedem Wort zu, das Sie gesagt haben, insbesondere dem Teil "Blind Copy a Convention". Ich lese gerade einen Code und der null = Objektstil nervt mich so sehr, dass ich ihn nachschlage und hierher komme. Was dachte der Kodierer?
Adrian M

28

Dies ist in Java (1.5+) nur dann von großem Wert, wenn der Objekttyp ist Boolean. In diesem Fall kann dies immer noch nützlich sein.

if (object = null)verursacht in Java 1.5+ keinen Kompilierungsfehler, wenn das Objekt ein ist Boolean, würde aber NullPointerExceptionzur Laufzeit ein auslösen .


Du hast wahrscheinlich gemeint, dass es zu einem Kompilierungsfehler führen wird :)
vava

7
Nein, es wird kein Kompilierungsfehler verursacht, wenn das Objekt boolesch ist.
Chandra Sekar

Ist es nicht für jeden Objekttyp außer Boolean gleich?
Ciro Santilli 法轮功 冠状 病 六四 事件 5

2
Bei nicht-booleschen Typen wird der Code nicht kompiliert, da der Typ des Ausdrucks "object = null" nicht boolesch ist. Aufgrund des automatischen Boxens wird es für Boolean kompiliert.
Chandra Sekar

Aber warum dieses Verhalten für Boolean? Irgendwelche Gründe?
Rohit Banga

9

In Java gibt es keinen guten Grund.

Ein paar andere Antworten haben behauptet, dass es daran liegt, dass Sie versehentlich eine Zuordnung anstelle von Gleichheit vornehmen können. Aber in Java muss ein Boolescher Wert in einem if enthalten sein.

if (o = null)

wird nicht kompiliert.

In Java kann dies nur dann von Bedeutung sein, wenn die Variable boolesch ist:

int m1(boolean x)
{
    if (x = true)  // oops, assignment instead of equality

4
Aber warum würdest du jemals schreiben == trueoder gleich == true == true.
Tom Hawtin - Tackline

7
Es gibt keinen guten Grund zu schreiben == true. Aber ich habe in meiner Karriere so viel schlechten Code gesehen, dass ich nicht mehr frage, warum jemand etwas schreiben würde und einfach akzeptiere, dass einige Leute unnötigen / fragwürdigen Code geschrieben haben.
R Samuel Klatchko

1
Tatsächlich fliegt eine Menge schlechter Code herum, wenn man ihn x == trueals schlecht ansieht, weil er fälschlicherweise so geschrieben werden könnte x = true, dass es nicht viel Sinn macht, ihn in true == xstatt nur zu ändern x.
Holger

9

Dies hängt auch eng zusammen mit:

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

Das ist praktisch, wenn Sie sich nicht mit NPEs befassen möchten:

if (bar!=null && bar.equals("foo")) {

kann bequem sein, kann aber gefährlich sein blue-walrus.com/2010/11/…
Oliver Watkins

@OliverWatkins: Ich finde diesen Artikel schwach. Angenommen, die Variable war vom Typ int. Wenn nicht initialisiert, wäre der Wert 0 und das Versprechen des Artikels würde nicht gelten. Die Tatsache, dass Strings Objekte und Ints Primitive sind, spielt keine Rolle für die Tatsache, dass ein Programmierer möglicherweise vergisst, eine Variable zu initiieren. In dieser Frage lösen wir einfach die Null-String-Vergleichssache.
Cherouvim

@cherouvim Die Tatsache, dass intes sich um einen primitiven Typ handelt , ist relevant, da es unmöglich ist, sich equalsauf einen zu berufen int. Daher macht es keinen Sinn, darüber zu diskutieren, ob x.equals(constant)oder constant.equals(x)für intWerte. Und für IntegerWerte ist der Standardwert nulleher als 0.
Holger

5

Dieser Trick soll verhindern v = null Tippfehler verhindern.

Java erlaubt aber nur boolesche Ausdrücke als if() Bedingungen, so dass ein Trick nicht viel Sinn macht. Der Compiler findet diese Tippfehler trotzdem.

Es ist jedoch immer noch ein wertvoller Trick für C / C ++ - Code.


3

Aus dem gleichen Grund machst du es in C; Zuweisung ist ein Ausdruck, daher setzen Sie das Literal links, damit Sie es nicht überschreiben können, wenn Sie es versehentlich =anstelle von verwenden ==.


Es ist jedoch nur ein Problem in Java für boolesche Typen, oder? Jede andere Art von Zuweisung hat keinen booleschen Typ und sollte einen Compilerfehler verursachen.
Scott Smith

1
Nein, der Java-Compiler wird diese Art von Tippfehler in beliebiger Reihenfolge
abfangen

@Jijoy - Ich denke, das hat nichts mit Leistung zu tun. Dies klingt nach einem alten Trick in C, um den gefürchteten Fehler bei der Zuweisung innerhalb eines bedingten Ausdrucks zu vermeiden. Die Idee war, dass, wenn Sie versuchen zu überprüfen, ob xgleich ist 5, wenn Sie versehentlich tippen if (x = 5), es leise kompiliert wird (und immer auswertet true, unabhängig vom Wert von x). Wenn Sie es sich jedoch zur Gewohnheit machen, immer zuerst das Literal anzugeben: 'if (5 = x)', kann der Compiler Ihre Arbeit überprüfen und Ihnen im Debugger Zeit sparen. Moderne Compiler machen diese Gewohnheit unnötig.
Scott Smith

6
-1: Wenn Sie versehentlich = verwenden, wird es nicht in Java kompiliert. Der Grund von C trifft also nicht zu.
Jon Skeet

Technisch gesehen könnte es einen Unterschied machen, wenn objes vom Typ java.lang.Boolean(großes B) wäre (ich denke, nicht wirklich ausprobiert oder so).
Tom Hawtin - Tackline

3

Das ist für Leute, die es vorziehen, die Konstante auf der linken Seite zu haben. In den meisten Fällen verhindert die Konstante auf der linken Seite, dass die NullPointerException ausgelöst wird (oder dass ein anderer Nullcheck ausgeführt wird). Zum Beispiel führt die String-Methode gleich auch eine Nullprüfung durch. Wenn Sie die Konstante links haben, können Sie den zusätzlichen Scheck nicht ausstellen. Was auf andere Weise auch später durchgeführt wird. Der Nullwert links ist nur konsistent.

mögen:

 String b = null;
 "constant".equals(b);  // result to false
 b.equals("constant");  // NullPointerException
 b != null && b.equals("constant");  // result to false

Dieses Verstecken von NPE macht es nur noch schwieriger, Fehler weiter stromabwärts zu finden
Oliver Watkins

2

Es ist eine Yoda-Bedingung, die auf unterschiedliche Weise schreibt

In Java

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

Yoda Zustand

String myString = null;
if ("foobar".equals(myString)) { /* ... */ } // will be false 

1

Vergleichen Sie mit folgendem Code:

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

Ausgabe (nach mehreren Ausführungen):

null != pingResult
325737
pingResult != null
47027

Daher pingResult != nullist der Gewinner.


7
Führen Sie Ihren Test in einer zusätzlichen Schleife durch! Oder wechseln Sie einfach die IF-Anweisungen. Lange Rede, kurzer Sinn: Es gibt keinen Unterschied! Die erste Schleife ist immer langsamer.
Marcel Jaeschke

In diesem Test ist pingResult immer ungleich Null. Was passiert mit dem Timing von pingResult ist null? Ich wette, es ist plattformunabhängig, aber auf meinem Oracle Java 1.6 / Linux-Stack sind die Ergebnisse ziemlich gleichmäßig (in einer Schleife), außer wenn pingResult null ist, sind beide Überprüfungen einige Prozent schneller.
Oger Psalm33

1
Wenn Sie "pingResult! = null block vor null! = pingResult block setzen, ergibt sich so etwas wie" pingResult! = null 325737 "
Sola Yang

Wie @Sola Yang sagt, wenn Sie pingResult! = Null vor setzen, werden Sie feststellen, dass es länger dauert als null! = PingResult. Wenn pingResult! = Null schneller als null! = PingResult war, gibt die IDE (wie IntelliG, Eclipse, ...) eine Warnung aus, um die Entwickler zu zwingen, diese Rolle zu verwenden;)
adil.hilmi

1

Aufgrund seiner kommutativen Eigenschaft ist der einzige Unterschied zwischen object == nullund null == object(der Yoda-Version ) kognitiver Natur : wie der Code vom Leser gelesen und verdaut wird. Ich kenne die endgültige Antwort zwar nicht, aber ich weiß, dass ich es persönlich vorziehe , das Objekt, das ich inspiziere, mit etwas anderem zu vergleichen, anstatt etwas anderes mit dem Objekt zu vergleichen, das ich inspiziere , wenn dies Sinn macht. Beginnen Sie mit dem Thema und dann mit dem Wert, mit dem Sie es vergleichen möchten.

In einigen anderen Sprachen ist dieser Vergleichsstil nützlicher.

Um sich vor einem fehlenden "=" - Zeichen im Allgemeinen zu schützen, halte ich das Schreiben null == objectfür einen fehlgeleiteten Akt der defensiven Programmierung . Der bessere Weg, um diesen bestimmten Code zu umgehen, besteht darin, das Verhalten mit einem Junit-Test zu garantieren. Denken Sie daran, dass der mögliche Fehler, ein "=" zu verpassen, nicht von den Eingabeargumenten der Methode abhängt - Sie sind nicht von der richtigen Verwendung dieser API durch andere Personen abhängig -, sodass ein Junit-Test perfekt ist, um sich stattdessen davor zu schützen. Auf jeden Fall sollten Sie Junit-Tests schreiben, um das Verhalten zu überprüfen. Ein fehlendes "=" fällt natürlich in den Geltungsbereich.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.