Java: Wie überprüfe ich, ob das Objekt null ist?

87

Ich erstelle eine Anwendung, die Bilder aus dem Web abruft. Falls das Bild nicht abgerufen werden kann, sollte ein anderes lokales Bild verwendet werden.

Beim Versuch, die folgenden Zeilen auszuführen:

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

Die Zeile if (drawable.equals (null)) löst eine Ausnahme aus, wenn drawable null ist.

Weiß jemand, wie der Wert von drawable überprüft werden soll, um keine Ausnahme auszulösen, falls er null ist, und um das lokale Image abzurufen (execute drawable = getRandomDrawable ())?

Niko Gamulin
quelle
23
Verwenden Sie if (drawable == null). Das Aufrufen einer Methode für ein NULL-Objekt ist eine NullPointerException.
Diciu
3
Warum schreibst du nicht eine übliche Antwort anstelle eines Kommentars, diciu?
Deamon
@JaredBurrows Bearbeiten Sie den Code in einer Frage nicht so, dass der Zweck der Frage verfehlt wird!
Gilles 'SO - hör auf böse zu sein'
@ Gilles Lesen Sie meinen redaktionellen Kommentar, ich habe den Code lesbarer gemacht.
Jared Burrows
@JaredBurrows Nein, Ihre Bearbeitung war keine Änderung der Formatierung. Sie haben nicht funktionierenden Code, der Gegenstand der Frage war, in Arbeitscode geändert, der die Frage in Frage stellte.
Gilles 'SO - hör auf böse zu sein'

Antworten:

35

Bearbeitete Java 8-Lösung:

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

Sie können drawable finalin diesem Fall deklarieren .

Wie Chasmo betonte, unterstützt Android Java 8 derzeit nicht. Diese Lösung ist also nur in anderen Kontexten möglich.

Deamon
quelle
7
Wahrscheinlich keine gute Idee - Sie kehren zu Fortran 60 zurück, wo beide Seiten der Bedingung ausgewertet werden, dann wird nur eine verwendet. Dies ist schlecht, wenn der nicht verwendete Zweig eine Berechnung hat, was meistens der Fall ist. Daher ist dies keine allgemein nützliche Methode. Ich würde die Bedingung in die CommonKlasse verschieben und Ihnen erlauben, eine Fallback-URL anzugeben und die Verantwortlichkeiten zusammenzuhalten.
Pete Kirkham
1
Das Beispiel wurde jetzt in Java 8 vollständig neu geschrieben, sodass meine Lösung nicht mehr unter nutzlosen Auswertungen leidet (wie @PeteKirkham in meiner ursprünglichen Lösung hervorhob).
Deamon
1
Android unterstützt Java 8 nicht. Es unterstützt nur bis zu Java 7 (wenn Sie Kitkat haben) und es hat immer noch keine aufgerufene Dynamik, nur den neuen Syntaxzucker. Außerdem Optional.ofbedeutet dies, dass der Wert nicht null ist und daher nicht erforderlich orElseGetist. Sie sollten Optional.ofNullablein diesem Fall verwenden.
Martin Seeler
178
Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable == null) {
    drawable = getRandomDrawable();
}

Die equals()Methode überprüft Wert Gleichheit, was bedeutet , dass sie die vergleicht Inhalt von zwei Objekten. Da nulles sich nicht um ein Objekt handelt, stürzt dies ab, wenn Sie versuchen, den Inhalt Ihres Objekts mit dem Inhalt von zu vergleichen null.

Der ==Operator prüft auf Referenzgleichheit , dh es wird geprüft , ob die beiden Objekte tatsächlich dasselbe Objekt sind . Dies erfordert nicht, dass die Objekte tatsächlich existieren. Zwei nicht vorhandene Objekte ( nullReferenzen) sind ebenfalls gleich.

Thomas
quelle
56
Ich möchte einen sehr wertvollen Tipp hinzufügen: Wenn Sie Zeichenfolgen oder Konstanten vergleichen müssen, setzen Sie diese immer an die erste Stelle in der equals-Klausel. (if ("coyote" .equals (myDogString))) ist viel besser als (if (myDogString.equals ("coyote"))), da myDogString im zweiten Fall null sein kann und eine NPE auslöst, während dies im ersten Fall nicht der Fall ist Es spielt keine Rolle, ob myDogString null ist.
Thorsten S.
20
Bekannt als Yoda-Bedingung: "Wenn ein Kojote, ist der Hund ..."
Thomas
1
Ich möchte auch hinzufügen, dass es seit Java 7 eine Objects.equals () -Methode gibt, mit der Sie sich nicht um die Yoda-Syntax
kümmern müssen
20

Ich benutze diesen Ansatz:

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

Auf diese Weise verbessert sich die Lesbarkeit der Zeile. Wenn ich eine Quelldatei schnell durchlese, sehe ich, dass es sich um eine Nullprüfung handelt.

In Bezug darauf, warum Sie .equals()ein Objekt nicht aufrufen können, das sein kann null; wenn die Objektreferenz Sie (nämlich ‚ziehbar‘) haben ist in der Tat null, es nicht auf dem Heap auf ein Objekt zeigen. Dies bedeutet, dass sich auf dem Heap kein Objekt befindet, auf dem der Aufruf erfolgreich sein equals()kann.

Viel Glück!

aus Kaffee
quelle
4
Ich bevorzuge auch das Konstrukt if (<Konstante> == <Variable>), um mich vor versehentlicher Zuweisung zu schützen.
Scott
8

DIY

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

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

Die obige Zeile ruft die Methode "equals (...)" für das zeichnbare Objekt auf.

Wenn also drawable nicht null ist und es sich um ein reales Objekt handelt, ist alles in Ordnung. Wenn Sie die Methode "equals (null)" aufrufen, wird "false" zurückgegeben.

Wenn "drawable" jedoch null ist, bedeutet dies, dass die Methode "equals (...)" für ein Nullobjekt aufgerufen wird und eine Methode für ein nicht vorhandenes Objekt aufgerufen wird, sodass "NullPointerException" ausgelöst wird.

Verwenden Sie Folgendes, um zu überprüfen, ob ein Objekt vorhanden und nicht null ist

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

In der obigen Bedingung prüfen wir, ob die Referenzvariable "drawable" null ist oder einen Wert enthält (Verweis auf ihr Objekt), sodass keine Ausnahme ausgelöst wird, falls drawable als Prüfung null ist

null == null

ist gültig.

Yatendra Goel
quelle
5

if (yourObject instanceof yourClassName)wird bewerten, falseob yourObjectist null.

Heapuser
quelle
0

Es ist wahrscheinlich etwas effizienter, eine NullPointerException abzufangen. Die obigen Methoden bedeuten, dass die Laufzeit zweimal nach Nullzeigern sucht.

An Herrn
quelle
1
Wo ist die Double-Check-In- if x == nullLösung?
Deamon
Nach der if-Anweisung sucht die Laufzeit erneut nach einem Nullzeiger, wenn das Objekt verwendet wird. Ich weiß jedoch nicht, ob dies vom Compiler optimiert wird oder nicht.
Tom R
4
Dies widerspricht der herkömmlichen Weisheit und verwendet Ausnahmen als Kontrollfluss.
James
1
Ausnahmen sind sehr teuer, da sie eine ganze Stapelspur erstellen müssen.
Deamon
0

Verwenden Sie Google Guava Libs , um die is-null-Prüfung durchzuführen (Deamons Update).

Drawable drawable = Optional.of(Common.getDrawableFromUrl(this, product.getMapPath())).or(getRandomDrawable());
Bala
quelle
Verwenden Sie Java 8 Optionalheute besser .
Deamon
-1

Nur um Oracle Java Source Developer einige Ideen zu geben :-)

Die Lösung existiert bereits in .Net und ist besser lesbar!

In Visual Basic .Net

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

In C #

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

Diese Lösungen sind leistungsstark als optionale Java-Lösung (Standardzeichenfolge wird nur ausgewertet, wenn der ursprüngliche Wert null ist) ohne Verwendung des Lambda-Ausdrucks, nur durch Hinzufügen eines neuen Operators.

Um den Unterschied zur Java-Lösung schnell zu erkennen, habe ich die beiden Java-Lösungen hinzugefügt

Verwenden von Optional in Java

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

Verwenden von {} in Java

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

Persönlich mag ich VB.Net, aber ich bevorzuge ?? C#oder if {}Lösung in Java ... und Sie?

schlebe
quelle