Java null check warum warum == anstelle von .equals () verwenden


125

In Java wird mir gesagt, dass man bei einer Nullprüfung == anstelle von .equals () verwenden soll. Was sind die Gründe dafür?


12
Am einfachsten ist es, die Nullprüfung zu überprüfen equals()und zu sehen. Wenn Sie es versuchen, wird es sofort offensichtlich sein
Goran Jovic

Übrigens, eine Google-Suche mit den Schlüsselwörtern "Java Null Check" (ohne Anführungszeichen) gab mir als einer der Top-Hits diesen Thread , der die gleichen Informationen wie die Antworten hier hat.
Mitch Schwartz

Antworten:


179

Das sind zwei völlig verschiedene Dinge. ==vergleicht die Objektreferenz, falls vorhanden, die in einer Variablen enthalten ist. .equals()prüft, ob zwei Objekte gemäß ihrem Vertrag gleich sind, was Gleichheit bedeutet. Es ist durchaus möglich, dass zwei unterschiedliche Objektinstanzen gemäß ihrem Vertrag "gleich" sind. Und dann gibt es noch das kleine Detail, dass equalses sich um eine Methode handelt. Wenn Sie versuchen, sie für eine nullReferenz aufzurufen , erhalten Sie eine NullPointerException.

Zum Beispiel:

class Foo {
    private int data;

    Foo(int d) {
        this.data = d;
    }

    @Override
    public boolean equals(Object other) {
        if (other == null || other.getClass() != this.getClass()) {
           return false;
        }
        return ((Foo)other).data == this.data;
    }

    /* In a real class, you'd override `hashCode` here as well */
}

Foo f1 = new Foo(5);
Foo f2 = new Foo(5);
System.out.println(f1 == f2);
// outputs false, they're distinct object instances

System.out.println(f1.equals(f2));
// outputs true, they're "equal" according to their definition

Foo f3 = null;
System.out.println(f3 == null);
// outputs true, `f3` doesn't have any object reference assigned to it

System.out.println(f3.equals(null));
// Throws a NullPointerException, you can't dereference `f3`, it doesn't refer to anything

System.out.println(f1.equals(f3));
// Outputs false, since `f1` is a valid instance but `f3` is null,
// so one of the first checks inside the `Foo#equals` method will
// disallow the equality because it sees that `other` == null

meinst du public int data?
Jé Queue

@Xepoch: Nein, ich erstelle im Allgemeinen keine öffentlichen Felder (obwohl es für dieses Beispiel so oder so nicht wirklich wichtig ist). Warum?
TJ Crowder

@TJ Crowder "Das sind zwei völlig verschiedene Dinge ..." im Allgemeinen ja. Die Standardimplementierung von beiden ist jedoch dieselbe, wenn mein Verständnis korrekt ist. Mit Blick auf den Quellcode führt .equals () im Grunde genommen eine == Prüfung durch. hg.openjdk.java.net/jdk7/jdk7/jdk/file/tip/src/share/classes/…
Ayush

1
@ Ayush - Das ist die Standardeinstellung in Object, ja. Es wird jedoch von einer großen Anzahl der JDK-Klassen überschrieben. Aber es geht nicht um Implementierung, sondern um Semantik. (Randnotiz: JDK7 ist sehr veraltet.)
TJ Crowder

Richtig, das macht Sinn, wollte nur klarstellen.
Ayush

38

wenn Sie rufen .equals()auf , nulldie Sie erhaltenNullPointerException

Es ist daher immer ratsam, die Nichtigkeit zu überprüfen, bevor Sie die Methode aufrufen, wo immer sie gilt

if(str!=null && str.equals("hi")){
 //str contains hi
}  

Siehe auch


34
Ihr Beispiel ist im Allgemeinen besser geschrieben als if ("hi".equals(str)).
ColinD

3
@ user368186: Es geht nicht darum, ob die Methode equals eine Nullprüfung enthält. Wenn Ihre Objektreferenz null ist, löst der Aufruf someObject.equals(null)ein aus, NullPointerExceptionohne jemals die Methode equals einzugeben.
Dave Costa

2
@ColinD Stimmen Sie zu, nur hier zu demonstrieren
Jigar Joshi

2
Es ist immer ratsam, Nullen um jeden Preis zu vermeiden, damit Sie überhaupt keine Nullprüfungen benötigen;).
Fwielstra

2
Sie können immer verwenden Objects.equals(a, b)Es wird keine NullPointerException auslösen, aber es hängt immer noch von der "gleichen" Methode der "a" und "b" ab
Dominik Minc

29

Zusätzlich zur akzeptierten Antwort ( https://stackoverflow.com/a/4501084/6276704 ):

Seit Java 1.7 empfehle ich diese Funktion, wenn Sie zwei Objekte vergleichen möchten, die möglicherweise null sind:

Objects.equals(onePossibleNull, twoPossibleNull)

java.util.Objects

Diese Klasse besteht aus statischen Dienstprogrammmethoden für die Bearbeitung von Objekten. Diese Dienstprogramme umfassen null-sichere oder null-tolerante Methoden zum Berechnen des Hash-Codes eines Objekts, zum Zurückgeben einer Zeichenfolge für ein Objekt und zum Vergleichen zweier Objekte.

Seit: 1.7


2
Nur um es für andere sichtbarer zu machen (siehe Antwort von chin90 oder JavaDoc ): Objects.equals(null, null)wird zurückkehren true- denken Sie daran.
Thomas

20

In Java sind 0 oder null einfache Typen und keine Objekte.

Die Methode equals () ist nicht für einfache Typen erstellt. Einfache Typen können mit == abgeglichen werden.


4
upvote für die eigentliche Antwort, die am nützlichsten ist, im Gegensatz zu der offensichtlichen "NullPointerException wird zurückgegeben" herp derp Antwort.
volk

4
foo.equals(null)

Was passiert, wenn foo null ist?

Sie erhalten eine NullPointerException.


3

Wenn eine Objektvariable null ist, kann keine equals () -Methode aufgerufen werden, daher ist eine Objektreferenzprüfung von null korrekt.


2

Wenn Sie versuchen, bei einer Nullobjektreferenz gleich aufzurufen, wird eine Nullzeigerausnahme ausgelöst.


2

Laut Quellen spielt es keine Rolle, was für die Implementierung der Standardmethode verwendet werden soll:

public boolean equals(Object object) {
    return this == object;
}

equalsIn der benutzerdefinierten Klasse können Sie sich jedoch nicht sicher sein .


Es ist wichtig, da equalsnur zurückkehren falseoder ein verursachen kann NullPointerException(oder etwas anderes, wenn die Überschreibungsmethode equalsUnsinn ist).
Tom

2

Wenn wir die Methode => .equals verwenden

if(obj.equals(null))  

// Which mean null.equals(null) when obj will be null.

Wenn Ihr Objekt null ist, wird eine Nullpunktausnahme ausgelöst.

also sollten wir == verwenden

if(obj == null)

Es werden die Referenzen verglichen.


2

Object.equals ist null-sicher. Beachten Sie jedoch, dass object.equals true zurückgibt, wenn zwei Objekte null sind. Überprüfen Sie daher, ob die zu vergleichenden Objekte nicht null sind (oder Nullwerte enthalten), bevor Sie object.equals für verwenden Vergleich.

String firstname = null;
String lastname = null;

if(Objects.equals(firstname, lastname)){
    System.out.println("equal!");
} else {
    System.out.println("not equal!");
}

Das obige Beispiel-Snippet gibt gleich zurück!


Wie vom JavaDoc angegeben (es ist immer ratsam, diese zu lesen): Consequently, if both arguments are null, true is returned. ...:)
Thomas

1

Da gleich eine von der Objektklasse abgeleitete Funktion ist, vergleicht diese Funktion Elemente der Klasse. Wenn Sie es mit null verwenden, wird false zurückgegeben, da der Klasseninhalt nicht null ist. Außerdem vergleicht == die Referenz auf ein Objekt.


Nun, das Ergebnis kann nur sein falseoder NullPointerException(wenn equalses nicht zu etwas Schlechtem überschrieben wird).
Tom

1

Hier ist ein Beispiel, wo str != nullaber str.equals(null)bei der Verwendungorg.json

 JSONObject jsonObj = new JSONObject("{field :null}");
 Object field = jsonObj.get("field");
 System.out.println(field != null);        // => true
 System.out.println( field.equals(null)); //=> true
 System.out.println( field.getClass());  // => org.json.JSONObject$Null




BEARBEITEN: Hier ist die org.json.JSONObject $ Null- Klasse:

/**
 * JSONObject.NULL is equivalent to the value that JavaScript calls null,
 * whilst Java's null is equivalent to the value that JavaScript calls
 * undefined.
 */
private static final class Null {

    /**
     * A Null object is equal to the null value and to itself.
     *
     * @param object
     *            An object to test for nullness.
     * @return true if the object parameter is the JSONObject.NULL object or
     *         null.
     */
    @Override
    public boolean equals(Object object) {
        return object == null || object == this;
    }  
}

Das Problem hierbei ist, dass field.equals(null)true zurückgegeben wird. Dies bricht das übliche Java-Verhalten und ist daher verwirrend. field.equals("null")Zumindest aus meiner Sicht sollte es nur funktionieren . Ich weiß nicht, warum die Bibliotheksentwickler dachten, dass dies gut zu unterstützen wäre.
Tom

Übrigens hat Ihr erster Satz ein Grammatikproblem und es ist unklar, was Sie damit meinen. Meinen Sie "Hier ist ein Beispiel, wo str != nullund str.equals(null)kehren Sie zurück, truewenn Sie org.json verwenden ."?
Tom

Ich denke, das liegt daran, dass der jsonObjectSchlüssel "Feld" enthält, weshalb er fieldnicht null ist. Er hat eine Referenz, die das json.org.JSONObject$Null Objekt enthält
dina

Ja, aber ich würde nicht Nullgerne behandeln nullund "null"stattdessen verwenden. Aber ich denke, sie haben das getan, um zu vermeiden, dass Strings benötigt werden. Aber auch mit dieser Bibliothek field.equals(null)ist fast immer noch ein Thema: P.
Tom

0

So werde ich nie verwirrt und vermeide Probleme mit dieser Lösung:

if(str.trim().length() <=0 ) {
   // is null !
}

5
Wenn str null ist, ist dies ein NPE
typoerrpr

Außerdem ist eine leere Zeichenfolge ( ""mit der Länge 0) etwas völlig anderes als eine nullReferenz (dh keine Zeichenfolge).
Thomas

0

Ich bin gestern Abend auf diesen Fall gestoßen.
Ich bestimme das einfach so:

Gibt es nicht equals () Methode für null
So können Sie nicht invoke eine inexistent Methode , wenn Sie nicht haben
- >>> Das ist Grund dafür , warum wir verwenden == überprüfen null


0

Ihr Code verstößt gegen Demeters Gesetz. Deshalb ist es besser, das Design selbst zu überarbeiten. Als Problemumgehung können Sie Optional verwenden

   obj = Optional.ofNullable(object1)
    .map(o -> o.getIdObject11())
    .map(o -> o.getIdObject111())
    .map(o -> o.getDescription())
    .orElse("")

oben ist die Hierarchie eines Objekts zu überprüfen, also einfach verwenden

Optional.ofNullable(object1) 

wenn Sie nur ein Objekt überprüfen müssen

Hoffe das hilft !!!!


-3

Das kannst du immer tun

if (str == null || str.equals(null))

Dadurch wird zuerst die Objektreferenz und dann das Objekt selbst überprüft, sofern die Referenz nicht null ist.


if (str == null || str.equals (null) || str.equals (""))
Lou Morda

Ich habe Ihre Antwort verwendet und einen Scheck für eine leere Zeichenfolge hinzugefügt! Wenn ich mich nicht irre, sind null und "" nicht dasselbe.
Lou Morda

4
Ist es nicht völlig redundant, eine zweite Prüfung auf Null hinzuzufügen?
Justin Rowe

2
@ JustinRowe Es ist nicht nur redundant, es ist auch sehr falsch. Bitte, mach niemals so etwas x.equals(null).
Tom

@ Tom, JustinRowe siehe meine Antwort oben, warum dies nicht redundant oder vollständig Müll Stackoverflow.com/questions/4501061/…
Dina
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.