Ich habe festgestellt, dass viele Java 8-Methoden in Oracle JDK verwenden Objects.requireNonNull()
, die intern ausgelöst werden, NullPointerException
wenn das angegebene Objekt (Argument) istnull
.
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
Aber NullPointerException
wird trotzdem , wenn ein geworfenernull
Objekt dereferenziert wird. Also, warum sollte man diese zusätzliche Nullprüfung durchführen und werfen
NullPointerException
?
Eine offensichtliche Antwort (oder ein Vorteil) ist, dass Code dadurch besser lesbar wird, und ich stimme zu. Ich bin gespannt auf weitere Gründe für die Verwendung
Objects.requireNonNull()
zu Beginn der Methode.
java
java-8
nullpointerexception
user4686046
quelle
quelle
Objects.requireNonNull
, hat Ihr Code keine Verzweigung, sodass Sie mit einem einzigen Durchgang einesAntworten:
Weil Sie dadurch Dinge explizit machen können. Mögen:
Oder kürzer:
Jetzt wissen Sie :
new()
Vergleichen Sie das mit: Sie erstellen heute ein Foo-Objekt und rufen morgen eine Methode auf, die dieses Feld verwendet und wirft. Höchstwahrscheinlich werden Sie morgen nicht wissen, warum diese Referenz gestern null war, als sie an den Konstruktor übergeben wurde!
Mit anderen Worten: Indem Sie diese Methode explizit verwenden, um eingehende Referenzen zu überprüfen , können Sie den Zeitpunkt steuern, zu dem die Ausnahme ausgelöst wird. Und meistens möchten Sie so schnell wie möglich scheitern !
Die Hauptvorteile sind:
bar
nicht null ist - und Sie brauchen daher keineif (bar == null)
Überprüfungen an anderen Stellen!quelle
this.bar = Objects.requireNonNull(bar, "bar must not be null");
Objects.requireNonNull(bar, "bar must not be null");
. Danke für diesen einen.this.bar = Objects.requireNonNull(bar, "bar must not be null");
ist in Ordnung , in dem Bau, aber potenziell gefährlich in anderen Verfahren , wenn zwei oder mehr Variablen in dem gleichen Verfahren festgelegt werden. Beispiel: talkwards.com/2018/11/03/…Ausfallsicher
Der Code sollte so schnell wie möglich abstürzen. Es sollte nicht die Hälfte der Arbeit erledigen und dann die Null dereferenzieren und erst dann abstürzen, wenn die Hälfte der Arbeit erledigt bleibt und das System in einem ungültigen Zustand ist.
Dies wird allgemein als "früh scheitern" oder "schnell scheitern" bezeichnet .
quelle
Dies bedeutet, dass Sie das Problem sofort und zuverlässig erkennen .
Erwägen:
.NET macht dies besser, indem es trennt
NullReferenceException
("Sie haben einen Nullwert dereferenziert") vonArgumentNullException
("Sie hätten null nicht als Argument übergeben sollen - und das war für diesen Parameter). Ich wünschte, Java hätte das Gleiche getan, aber auch mit Nur aNullPointerException
, es ist immer noch viel einfacher, Code zu reparieren, wenn der Fehler an dem frühesten Punkt ausgelöst wird, an dem er erkannt werden kann.quelle
Die Verwendung
requireNonNull()
als erste Anweisungen in einer Methode ermöglicht es, die Ursache der Ausnahme sofort / schnell zu identifizieren.Die Stapelverfolgung zeigt deutlich an, dass die Ausnahme sofort nach Eingabe der Methode ausgelöst wurde, da der Aufrufer die Anforderungen / den Vertrag nicht eingehalten hat. Das Übergeben eines
null
Objekts an eine andere Methode kann zwar jeweils eine Ausnahme hervorrufen, die Ursache des Problems kann jedoch komplizierter zu verstehen sein, da die Ausnahme in einem bestimmten Aufruf desnull
Objekts ausgelöst wird , der möglicherweise viel weiter entfernt ist.Hier ist ein konkretes und reales Beispiel, das zeigt, warum wir es vorziehen müssen, im Allgemeinen schnell zu scheitern und insbesondere
Object.requireNonNull()
Parameter zu verwenden oder auf irgendeine Weise eine Null-Null-Prüfung für Parameter durchzuführen, die so konzipiert sind, dass dies nicht der Fall istnull
.Angenommen , eine
Dictionary
Klasse , die ein komponiertLookupService
und einList
vonString
darstellt Wörter enthalten in. Diese Felder sind so konzipiert, dass nicht ,null
und eine davon ist in den vergangenDictionary
Konstruktor.Nehmen wir nun eine "schlechte" Implementierung
Dictionary
ohnenull
Überprüfung im Methodeneintrag an (hier ist das der Konstruktor):Rufen wir nun den
Dictionary
Konstruktor mit einernull
Referenz für denwords
Parameter auf:Die JVM wirft die NPE auf diese Aussage:
Die Ausnahme wird in der
LookupService
Klasse ausgelöst, während der Ursprung weit früher liegt (derDictionary
Konstruktor). Dies macht die allgemeine Problemanalyse viel weniger offensichtlich.Ist
words
null
? Istwords.get(0) null
? Beide ? Warum sind das eine, das andere oder vielleicht beidenull
? Ist es ein Codierungsfehler inDictionary
(Konstruktor? Aufgerufene Methode?)? Ist es ein Codierungsfehler inLookupService
? (Konstruktor? aufgerufene Methode?)?Schließlich müssen wir mehr Code untersuchen, um den Fehlerursprung zu finden, und in einer komplexeren Klasse möglicherweise sogar einen Debugger verwenden, um leichter zu verstehen, was passiert ist.
Aber warum wird eine einfache Sache (ein Mangel an Nullprüfung) zu einem komplexen Problem?
Weil wir zugelassen haben, dass der anfängliche Fehler / Mangel bei einem bestimmten Komponentenleck bei niedrigeren Komponenten erkennbar ist.
Stell dir das vor
LookupService
kein lokaler Dienst, sondern ein Remote-Dienst oder eine Bibliothek eines Drittanbieters mit wenigen Debugging-Informationen, oder stellen Sie sich vor, Sie hätten nicht 2 Ebenen, sondern 4 oder 5 Ebenen von Objektaufrufen, bevornull
diese erkannt wurden? Das Problem wäre noch komplexer zu analysieren.Der Weg zu bevorzugen ist also:
Auf diese Weise keine Kopfschmerzen: Wir erhalten die Ausnahme ausgelöst, sobald diese empfangen wird:
Beachten Sie, dass ich hier das Problem mit einem Konstruktor veranschaulicht habe, ein Methodenaufruf jedoch dieselbe Nicht-Null-Prüfbedingung haben kann.
quelle
Als Randnotiz wurde dies schnell fehlgeschlagen, bevor
Object#requireNotNull
es vor Java-9 in einigen der JRE-Klassen selbst etwas anders implementiert wurde. Angenommen, der Fall:In Java-8 wird dies kompiliert als (nur die relevanten Teile)
Grundsätzlich eine Operation wie:
yourReference.getClass
- die fehlschlagen würde, wenn Ihre Referenz istnull
.In jdk-9 haben sich die Dinge geändert, in denen derselbe Code kompiliert wird wie
Oder im Grunde
Objects.requireNotNull (yourReference)
quelle
Die grundlegende Verwendung ist das
NullPointerException
sofortige Überprüfen und Werfen .Eine bessere Alternative (Verknüpfung), um dieselbe Anforderung zu erfüllen, ist die @ NoNull- Annotation von lombok.
quelle
Eine Nullzeigerausnahme wird ausgelöst, wenn Sie auf ein Mitglied eines Objekts zugreifen, das sich
null
zu einem späteren Zeitpunkt befindet.Objects.requireNonNull()
Überprüft sofort den Wert und löst sofort eine Ausnahme aus, ohne vorwärts zu gehen.quelle
Ich denke, es sollte in Kopierkonstruktoren und einigen anderen Fällen wie DI verwendet werden, deren Eingabeparameter ein Objekt ist. Sie sollten überprüfen, ob der Parameter null ist. Unter solchen Umständen können Sie diese statische Methode bequem verwenden.
quelle