Ich benutze object != null
viel, um zu vermeiden NullPointerException
.
Gibt es eine gute Alternative dazu?
Zum Beispiel benutze ich oft:
if (someobject != null) {
someobject.doCalc();
}
Dies sucht im obigen Snippet nach einem NullPointerException
für das someobject
Objekt.
Beachten Sie, dass die akzeptierte Antwort möglicherweise veraltet ist. Weitere Informationen finden Sie unter https://stackoverflow.com/a/2386013/12943 .
java
object
nullpointerexception
null
Goran Martinic
quelle
quelle
Option
Typ durch die mangelnde Bereitschaft der Sprache beeinträchtigt, zu kontrollieren oder zu verbietennull
. Ich erwähnte dies auf Hackernews und wurde herabgestimmt und sagte, dass "in Scala sowieso niemand null verwendet". Ratet mal, ich finde bereits Nullen in der von Kollegen geschriebenen Scala. Ja, sie "machen es falsch" und müssen darüber aufgeklärt werden, aber die Tatsache bleibt, dass dasAntworten:
Dies klingt für mich nach einem einigermaßen häufigen Problem, mit dem Nachwuchsentwickler irgendwann konfrontiert sind: Sie kennen die Verträge, an denen sie teilnehmen, entweder nicht oder vertrauen ihnen nicht und überprüfen sie defensiv auf Nullen. Darüber hinaus verlassen sie sich beim Schreiben ihres eigenen Codes in der Regel darauf, Nullen zurückzugeben, um etwas anzuzeigen, sodass der Aufrufer nach Nullen suchen muss.
Anders ausgedrückt, es gibt zwei Fälle, in denen die Nullprüfung auftritt:
Wenn null eine gültige vertragliche Antwort ist; und
Wo es keine gültige Antwort ist.
(2) ist einfach. Verwenden Sie entweder
assert
Anweisungen (Zusicherungen) oder lassen Sie Fehler zu (z. B. NullPointerException ). Assertions sind eine stark unterausgenutzte Java-Funktion, die in 1.4 hinzugefügt wurde. Die Syntax lautet:oder
Dabei
<condition>
handelt es sich um einen booleschen Ausdruck und<object>
um ein Objekt, dessentoString()
Methodenausgabe in den Fehler einbezogen wird.Eine
assert
Anweisung löst einError
(AssertionError
) aus, wenn die Bedingung nicht erfüllt ist. Standardmäßig ignoriert Java Zusicherungen. Sie können Zusicherungen aktivieren, indem Sie die Option-ea
an die JVM übergeben. Sie können Zusicherungen für einzelne Klassen und Pakete aktivieren und deaktivieren. Dies bedeutet, dass Sie Code mit den Zusicherungen während der Entwicklung und des Testens validieren und in einer Produktionsumgebung deaktivieren können, obwohl meine Tests so gut wie keine Auswirkungen auf die Leistung von Zusicherungen gezeigt haben.In diesem Fall ist es in Ordnung, keine Zusicherungen zu verwenden, da der Code nur fehlschlägt. Dies passiert, wenn Sie Zusicherungen verwenden. Der einzige Unterschied besteht darin, dass es bei Behauptungen früher, aussagekräftiger und möglicherweise mit zusätzlichen Informationen geschehen kann, die Ihnen helfen können, herauszufinden, warum es passiert ist, wenn Sie es nicht erwartet haben.
(1) ist etwas schwieriger. Wenn Sie keine Kontrolle über den Code haben, den Sie aufrufen, stecken Sie fest. Wenn null eine gültige Antwort ist, müssen Sie danach suchen.
Wenn es sich jedoch um Code handelt, den Sie steuern (und dies ist häufig der Fall), ist dies eine andere Geschichte. Vermeiden Sie die Verwendung von Nullen als Antwort. Mit Methoden, die Sammlungen zurückgeben, ist es einfach: Leere Sammlungen (oder Arrays) anstelle von Nullen fast immer zurückzugeben.
Bei Nicht-Sammlungen kann es schwieriger sein. Betrachten Sie dies als Beispiel: Wenn Sie diese Schnittstellen haben:
Dabei nimmt Parser rohe Benutzereingaben entgegen und findet etwas zu tun, möglicherweise wenn Sie eine Befehlszeilenschnittstelle für etwas implementieren. Jetzt können Sie den Vertrag so gestalten, dass er null zurückgibt, wenn keine entsprechende Aktion ausgeführt wird. Das führt zu der Nullprüfung, von der Sie sprechen.
Eine alternative Lösung besteht darin, niemals null zurückzugeben und stattdessen das Null-Objektmuster zu verwenden :
Vergleichen Sie:
zu
Dies ist ein viel besseres Design, da es zu einem präziseren Code führt.
Das heißt, vielleicht ist es für die findAction () -Methode völlig angemessen, eine Ausnahme mit einer aussagekräftigen Fehlermeldung auszulösen - insbesondere in diesem Fall, in dem Sie sich auf Benutzereingaben verlassen. Es wäre viel besser, wenn die findAction-Methode eine Ausnahme auslösen würde, als wenn die aufrufende Methode mit einer einfachen NullPointerException ohne Erklärung in die Luft jagen würde.
Oder wenn Sie der Meinung sind, dass der Try / Catch-Mechanismus zu hässlich ist, anstatt nichts zu tun, sollte Ihre Standardaktion dem Benutzer Feedback geben.
quelle
Wenn Sie eine Java-IDE wie JetBrains IntelliJ IDEA , Eclipse oder Netbeans oder ein Tool wie findbugs verwenden (oder verwenden möchten), können Sie dieses Problem mithilfe von Anmerkungen lösen.
Grundsätzlich hast du
@Nullable
und@NotNull
.Sie können in Methode und Parametern wie folgt verwenden:
oder
Das zweite Beispiel wird nicht kompiliert (in IntelliJ IDEA).
Wenn Sie die erste
helloWorld()
Funktion in einem anderen Code verwenden:Jetzt teilt Ihnen der IntelliJ IDEA-Compiler mit, dass die Prüfung nutzlos ist, da die
helloWorld()
Funktionnull
niemals zurückkehren wird.Parameter verwenden
wenn du so etwas schreibst wie:
Dies wird nicht kompiliert.
Letztes Beispiel mit
@Nullable
Dies tun
Und Sie können sicher sein, dass dies nicht passieren wird. :) :)
Es ist eine gute Möglichkeit, den Compiler mehr als sonst überprüfen zu lassen und Ihre Verträge durchzusetzen, um stärker zu werden. Leider wird es nicht von allen Compilern unterstützt.
In IntelliJ IDEA 10.5 und höher wurde die Unterstützung für alle anderen
@Nullable
@NotNull
Implementierungen hinzugefügt .Siehe Blog-Beitrag Flexiblere und konfigurierbarere @ Nullable / @ NotNull-Anmerkungen .
quelle
@NotNull
,@Nullable
Und andere nullness Anmerkungen sind Bestandteil von JSR 305 . Sie können sie auch verwenden, um potenzielle Probleme mit Tools wie FindBugs zu erkennen .@NotNull
&@Nullable
Schnittstellen im Paket lebencom.sun.istack.internal
. (Ich glaube, ich verbinde com.sun mit Warnungen über die Verwendung einer proprietären API.)@NotNull
und@Nullable
sind ist , dass sie schön verschlechtern , wenn der Quellcode durch ein System aufgebaut wird , die sie nicht versteht. Tatsächlich kann das Argument, dass der Code nicht portierbar ist, ungültig sein. Wenn Sie ein System verwenden, das diese Anmerkungen unterstützt und versteht, erhalten Sie den zusätzlichen Vorteil einer strengeren Fehlerprüfung, andernfalls erhalten Sie weniger davon, aber Ihr Code sollte trotzdem Bauen Sie gut, und die Qualität Ihres laufenden Programms ist DIE GLEICHE, da diese Anmerkungen zur Laufzeit ohnehin nicht erzwungen wurden. Außerdem sind alle Compiler benutzerdefiniert ;-)Wenn Nullwerte nicht erlaubt sind
Wenn Ihre Methode extern aufgerufen wird, beginnen Sie mit Folgendes:
Im Rest dieser Methode wissen Sie dann, dass dies
object
nicht null ist.Wenn es sich um eine interne Methode handelt (die nicht Teil einer API ist), dokumentieren Sie einfach, dass sie nicht null sein kann, und das war's.
Beispiel:
Wenn Ihre Methode jedoch nur den Wert weitergibt und die nächste Methode ihn usw. weitergibt, kann dies problematisch werden. In diesem Fall möchten Sie möglicherweise das obige Argument überprüfen.
Wenn null erlaubt ist
Das hängt wirklich davon ab. Wenn ich finde, dass ich so etwas oft mache:
Also verzweige ich mich und mache zwei völlig verschiedene Dinge. Es gibt kein hässliches Code-Snippet, da ich je nach Daten wirklich zwei verschiedene Dinge tun muss. Soll ich beispielsweise an der Eingabe arbeiten oder einen guten Standardwert berechnen?
Es ist eigentlich selten für mich, die Redewendung "
if (object != null && ...
" zu verwenden.Es kann einfacher sein, Ihnen Beispiele zu geben, wenn Sie Beispiele dafür zeigen, wo Sie normalerweise die Redewendung verwenden.
quelle
throw new IllegalArgumentException("object==null")
Wow, ich hasse es fast, eine weitere Antwort hinzuzufügen, wenn wir 57 verschiedene Möglichkeiten haben, die zu empfehlen
NullObject pattern
, aber ich denke, dass einige Leute, die an dieser Frage interessiert sind, gerne wissen möchten, dass in der Tabelle ein Vorschlag für Java 7 steht, "null-safe" hinzuzufügen Handling " - Eine optimierte Syntax für die Logik " Wenn nicht gleich Null ".Das Beispiel von Alex Miller sieht folgendermaßen aus:
Das
?.
Mittel de-referenziert den linken Bezeichner nur, wenn er nicht null ist, andernfalls wird der Rest des Ausdrucks als ausgewertetnull
. Einige Leute, wie das Java Posse-Mitglied Dick Wall und die Wähler bei Devoxx, lieben diesen Vorschlag wirklich, aber es gibt auch Widerstand, weil er tatsächlich zu einer stärkeren Verwendungnull
als Sentinel-Wert führen wird.Update: Ein offizieller Vorschlag für einen null-sicheren Operator in Java 7 wurde unter Project Coin eingereicht . Die Syntax unterscheidet sich ein wenig von dem obigen Beispiel, aber es ist der gleiche Begriff.
Update: Der Vorschlag für einen nullsicheren Operator hat es nicht in Project Coin geschafft. Diese Syntax wird in Java 7 also nicht angezeigt.
quelle
Wenn undefinierte Werte nicht zulässig sind:
Sie können Ihre IDE so konfigurieren, dass Sie vor einer möglichen Null-Dereferenzierung gewarnt werden. Siehe beispielsweise in Eclipse Einstellungen> Java> Compiler> Fehler / Warnungen / Nullanalyse .
Wenn undefinierte Werte zulässig sind:
Wenn Sie eine neue API definieren möchten, bei der undefinierte Werte sinnvoll sind , verwenden Sie das Optionsmuster (möglicherweise aus funktionalen Sprachen bekannt). Es hat folgende Vorteile:
Java 8 verfügt über eine integrierte
Optional
Klasse (empfohlen). für frühere Versionen gibt es Bibliothek Alternativen, zum Beispiel Guava ‚sOptional
oder FunctionalJava ‘ sOption
. Aber wie bei vielen Mustern im funktionalen Stil führt die Verwendung von Option in Java (sogar 8) zu einigen Boilerplates, die Sie mit einer weniger ausführlichen JVM-Sprache, z. B. Scala oder Xtend, reduzieren können.Wenn Sie sich mit einer API befassen müssen, die möglicherweise Nullen zurückgibt , können Sie in Java nicht viel tun. Xtend und Groovy haben den Elvis-Operator
?:
und den null-sicheren Dereferenzierungsoperator.?.
Beachten Sie jedoch, dass dies im Fall einer Nullreferenz null zurückgibt, sodass nur die ordnungsgemäße Behandlung von null "verschoben" wird.quelle
Nur für diese Situation -
Überprüfen Sie nicht, ob eine Variable null ist, bevor Sie eine equals-Methode aufrufen (ein Beispiel für einen Zeichenfolgenvergleich unten):
führt zu einem
NullPointerException
wennfoo
nicht existiert.Sie können dies vermeiden, wenn Sie Ihre
String
s wie folgt vergleichen :quelle
<object that you know that is not null>.equals(<object that might be null>);
. Es funktioniert für andere Methoden alsequals
wenn Sie den Vertrag kennen und diese Methodennull
Parameter verarbeiten können.Mit Java 8 kommt die neue
java.util.Optional
Klasse, die wohl einige der Probleme löst. Man kann zumindest sagen, dass es die Lesbarkeit des Codes verbessert und im Fall von öffentlichen APIs den Vertrag der API für den Client-Entwickler klarer macht.Sie arbeiten so:
Ein optionales Objekt für einen bestimmten Typ (
Fruit
) wird als Rückgabetyp einer Methode erstellt. Es kann leer sein oder einFruit
Objekt enthalten :Schauen Sie sich nun diesen Code an, in dem wir eine Liste von
Fruit
(fruits
) nach einer bestimmten Fruit-Instanz durchsuchen :Mit dem
map()
Operator können Sie eine Berechnung für ein optionales Objekt durchführen oder einen Wert daraus extrahieren.orElse()
Mit dieser Option können Sie einen Fallback für fehlende Werte bereitstellen.Natürlich ist die Prüfung auf Null / Leerwert weiterhin erforderlich, aber zumindest der Entwickler ist sich bewusst, dass der Wert möglicherweise leer ist und das Risiko, die Prüfung zu vergessen, begrenzt ist.
In einer von Grund auf neu erstellten API,
Optional
bei der ein Rückgabewert möglicherweise leer ist und ein einfaches Objekt nur dann zurückgegeben wird, wenn dies nicht möglich istnull
(Konvention), gibt der Clientcode möglicherweise Nullprüfungen für einfache Objektrückgabewerte auf ...Natürlich
Optional
könnte es auch als Methodenargument verwendet werden, vielleicht eine bessere Möglichkeit, optionale Argumente anzugeben, als in einigen Fällen 5 oder 10 Überladungsmethoden.Optional
bietet andere bequeme Methoden, z. B.orElse
die die Verwendung eines Standardwerts ermöglichen undifPresent
mit Lambda-Ausdrücken funktionieren .Ich lade Sie ein, diesen Artikel (meine Hauptquelle für das Schreiben dieser Antwort) zu lesen, in dem die
NullPointerException
(und im Allgemeinen Nullzeiger-) Problematik sowie die (Teil-) Lösung, die sich daraus ergibt,Optional
gut erklärt werden: Java Optional Objects .quelle
if(optional.isPresent()){ optional.get(); }
anstattoptional.ifPresent(o -> { ...})
Abhängig davon, welche Art von Objekten Sie überprüfen, können Sie möglicherweise einige der Klassen in den Apache Commons verwenden, z. B .: Apache commons lang und apache commons Sammlungen
Beispiel:
oder (je nachdem, was Sie überprüfen müssen):
Die StringUtils-Klasse ist nur eine von vielen. Es gibt einige gute Klassen in den Commons, die keine sichere Manipulation durchführen.
Hier folgt ein Beispiel, wie Sie die Null-Vallidierung in JAVA verwenden können, wenn Sie eine Apache-Bibliothek (commons-lang-2.4.jar) einschließen.
Und wenn Sie Spring verwenden, hat Spring auch die gleiche Funktionalität in seinem Paket, siehe Bibliothek (spring-2.4.6.jar)
Beispiel für die Verwendung dieser statischen Klasse aus spring (org.springframework.util.Assert)
quelle
Sie müssen nur dann nach Objekt! = Null suchen, wenn Sie den Fall behandeln möchten, in dem das Objekt möglicherweise null ist ...
Es gibt einen Vorschlag, neue Anmerkungen in Java7 hinzuzufügen, um mit null / notnull-Parametern zu helfen: http://tech.puredanger.com/java7/#jsr308
quelle
Ich bin ein Fan von "Fail Fast" -Code. Fragen Sie sich - tun Sie etwas Nützliches, wenn der Parameter null ist? Wenn Sie keine klare Antwort darauf haben, was Ihr Code in diesem Fall tun soll ... Das heißt, er sollte niemals null sein, ignorieren Sie ihn und lassen Sie eine NullPointerException auslösen. Der aufrufende Code macht für eine NPE genauso viel Sinn wie für eine IllegalArgumentException, aber für den Entwickler ist es einfacher zu debuggen und zu verstehen, was schief gelaufen ist, wenn eine NPE ausgelöst wird, als dass Ihr Code versucht, eine andere unerwartete Eventualität auszuführen Logik - was letztendlich dazu führt, dass die Anwendung trotzdem fehlschlägt.
quelle
Das Google-Sammlungsframework bietet eine gute und elegante Möglichkeit, die Nullprüfung durchzuführen.
In einer Bibliotheksklasse wie dieser gibt es eine Methode:
Und die Verwendung ist (mit
import static
):Oder in Ihrem Beispiel:
quelle
getThing().getItsThing().getOtherThing().wowEncapsulationIsBroken().setLol("hi");
Manchmal haben Sie Methoden, die mit ihren Parametern arbeiten, die eine symmetrische Operation definieren:
Wenn Sie wissen, dass b niemals null sein kann, können Sie es einfach tauschen. Es ist am nützlichsten für Gleichgestellte: Anstatt es
foo.equals("bar");
besser zu machen"bar".equals(foo);
.quelle
equals
(könnte jede Methode sein), dass null korrekt behandelt wird. Wirklich alles, was dies tut, ist die Verantwortung an jemand anderen (oder eine andere Methode) weiterzugeben.equals
(oder welche Methode auch immer) mussnull
sowieso nachsehen . Oder geben Sie ausdrücklich an, dass dies nicht der Fall ist.Anstelle des Nullobjektmusters, das seine Verwendung hat, können Sie Situationen in Betracht ziehen, in denen das Nullobjekt ein Fehler ist.
Wenn die Ausnahme ausgelöst wird, überprüfen Sie die Stapelverfolgung und beheben Sie den Fehler.
quelle
Null ist kein "Problem". Es ist ein wesentlicher Bestandteil eines vollständigen Modellierungswerkzeugsatzes. Software zielt darauf ab, die Komplexität der Welt zu modellieren, und Null trägt ihre Last. Null bedeutet "Keine Daten" oder "Unbekannt" in Java und dergleichen. Daher ist es angebracht, für diese Zwecke Nullen zu verwenden. Ich bevorzuge nicht das 'Null-Objekt'-Muster. Ich denke, es wirft das Problem auf , wer die Wächter beschützen wird.
Wenn du mich fragst, wie meine Freundin heißt, sage ich dir, dass ich keine Freundin habe. In der Java-Sprache gebe ich null zurück. Eine Alternative wäre, eine sinnvolle Ausnahme auszulösen, um auf ein Problem hinzuweisen, das nicht sein kann (oder nicht)
Geben Sie für eine "unbekannte Frage" eine "unbekannte Antwort". (Seien Sie null-sicher, wenn dies aus geschäftlicher Sicht korrekt ist.) Wenn Sie Argumente innerhalb einer Methode vor der Verwendung einmal auf null prüfen, werden mehrere Anrufer nicht mehr vor einem Aufruf überprüft.
Zurück führt zu einem normalen Logikfluss, um kein Foto einer nicht existierenden Freundin aus meiner Fotobibliothek zu erhalten.
Und es passt zur neuen Java-API (mit Blick auf die Zukunft)
Während es eher "normaler Geschäftsablauf" ist, für eine Person kein in der Datenbank gespeichertes Foto zu finden, habe ich in einigen anderen Fällen Paare wie unten verwendet
Und hassen Sie es nicht, zu tippen
<alt> + <shift> + <j>
(Javadoc in Eclipse zu generieren) und drei zusätzliche Wörter für Ihre öffentliche API zu schreiben. Dies wird mehr als genug für alle sein, außer für diejenigen, die keine Dokumentation lesen.oder
Dies ist ein eher theoretischer Fall, und in den meisten Fällen sollten Sie die Java-Null-Safe-API bevorzugen (falls sie in weiteren 10 Jahren veröffentlicht wird), sie gehört jedoch zu einer
NullPointerException
Unterklasse vonException
. Somit ist es eine FormThrowable
, die Bedingungen anzeigt, die eine vernünftige Anwendung möglicherweise fangen möchte ( javadoc )! Um den ersten Vorteil von Ausnahmen zu nutzen und Fehlerbehandlungscode von "normalem" Code zu trennen ( laut Java-Entwicklern ), ist es für mich angebracht, zu fangenNullPointerException
.Fragen könnten sich stellen:
F. Was ist, wenn
getPhotoDataSource()
null zurückgegeben wird?A. Es liegt an der Geschäftslogik. Wenn ich kein Fotoalbum finde, zeige ich Ihnen keine Fotos. Was ist, wenn appContext nicht initialisiert wird? Die Geschäftslogik dieser Methode lässt dies zu. Wenn dieselbe Logik strenger sein sollte als das Auslösen einer Ausnahme, ist sie Teil der Geschäftslogik, und es sollte eine explizite Prüfung auf Null verwendet werden (Fall 3). Die neue Java Null-Safe-API passt hier besser, um selektiv anzugeben, was impliziert und was nicht bedeutet, dass sie bei Programmiererfehlern ausfallsicher initialisiert werden muss.
Q. Redundanter Code könnte ausgeführt werden und unnötige Ressourcen könnten abgerufen werden.
A. Es könnte stattfinden, wenn
getPhotoByName()
versucht wird, eine Datenbankverbindung zu öffnen,PreparedStatement
den Personennamen zu erstellen und zuletzt als SQL-Parameter zu verwenden. Der Ansatz für eine unbekannte Frage gibt eine unbekannte Antwort (Fall 1) funktioniert hier. Vor dem Abrufen von Ressourcen sollte die Methode die Parameter überprüfen und bei Bedarf das Ergebnis "unbekannt" zurückgeben.F. Dieser Ansatz hat eine Leistungseinbuße aufgrund der Öffnung des Versuchsabschlusses.
A. Software sollte zunächst leicht zu verstehen und zu ändern sein. Erst danach konnte man über Leistung nachdenken und nur bei Bedarf! und wo nötig! ( Quelle ) und viele andere).
PS. Dieser Ansatz ist genauso sinnvoll zu verwenden, wie der vom "normalen" Code- Prinzip getrennte Fehlerbehandlungscode an einer bestimmten Stelle sinnvoll ist. Betrachten Sie das nächste Beispiel:
PPS. Für diejenigen, die schnell abstimmen (und nicht so schnell Dokumentation lesen), möchte ich sagen, dass ich in meinem Leben noch nie eine Null-Zeiger-Ausnahme (NPE) festgestellt habe. Diese Möglichkeit wurde jedoch absichtlich von den Java-Entwicklern entwickelt, da NPE eine Unterklasse von ist
Exception
. Wir haben einen Präzedenzfall in der Java-Geschichte, bei demThreadDeath
es sichError
nicht um einen Anwendungsfehler handelt, sondern nur, weil er nicht abgefangen werden sollte! Wie viel NPE passt zu einemError
alsThreadDeath
! Aber es ist nicht.Suchen Sie nur dann nach "Keine Daten", wenn die Geschäftslogik dies impliziert.
und
Wenn appContext oder dataSource nicht initialisiert wird, beendet die nicht behandelte Laufzeit NullPointerException den aktuellen Thread und wird von Thread.defaultUncaughtExceptionHandler verarbeitet (damit Sie Ihren bevorzugten Logger oder einen anderen Benachrichtigungsmechanismus definieren und verwenden können). Wenn nicht festgelegt, gibt ThreadGroup # uncaughtException einen Stacktrace für Systemfehler aus. Man sollte das Anwendungsfehlerprotokoll überwachen und das Jira-Problem für jede nicht behandelte Ausnahme öffnen, bei der es sich tatsächlich um einen Anwendungsfehler handelt. Der Programmierer sollte den Fehler irgendwo in der Initialisierung beheben.
quelle
NullPointerException
und Zurückkehrennull
ist schrecklich zu debuggen. Du landest sowieso später mit NPE und es ist wirklich schwer herauszufinden, was ursprünglich null war.if (maybeNull.hasValue()) {...}
also was ist der Unterschied zuif (maybeNull != null)) {...}
?Maybe<T>
oderOptional<T>
nicht in dem Fall, in dem SieT
möglicherweise null sind, aber in dem Fall, in dem es niemals null sein sollte. Wenn Sie einen Typ haben, der explizit bedeutet, dass "dieser Wert möglicherweise null ist - mit Vorsicht verwenden", und Sie einen solchen Typ konsistent verwenden und zurückgebenT
, können Sie davon ausgehen, dass er niemals null ist , wenn Sie in Ihrem Code einen einfachen alten Wert sehen . (Java 7 verfügt über eine neue
java.util.Objects
Dienstprogrammklasse, für die es einerequireNonNull()
Methode gibt. Alles was dies tut ist ein a zu werfen,NullPointerException
wenn sein Argument null ist, aber es bereinigt den Code ein wenig. Beispiel:Die Methode ist am nützlichsten für die Überprüfung unmittelbar vor einer Zuweisung in einem Konstruktor, bei der bei jeder Verwendung drei Codezeilen gespeichert werden können:
wird
quelle
doCalc(someObject)
.doCalc()
sind und NPE nicht sofort ausgelöst wird, wenn null angegeben wird, müssen Sie nach null suchen und NPE selbst werfen. DafürObjects.requireNonNull()
ist es da.Letztendlich ist die einzige Möglichkeit, dieses Problem vollständig zu lösen, die Verwendung einer anderen Programmiersprache:
nil
, und es wird absolut nichts passieren. Dies macht die meisten Nullprüfungen unnötig, kann jedoch die Diagnose von Fehlern erheblich erschweren.quelle
Häufiges "Problem" in Java.
Zunächst meine Gedanken dazu:
Ich denke, dass es schlecht ist, etwas zu "essen", wenn NULL übergeben wurde, wobei NULL kein gültiger Wert ist. Wenn Sie die Methode nicht mit einem Fehler beenden, bedeutet dies, dass in Ihrer Methode nichts schief gelaufen ist, was nicht der Fall ist. Dann geben Sie in diesem Fall wahrscheinlich null zurück, und in der Empfangsmethode suchen Sie erneut nach null, und es endet nie, und Sie erhalten "if! = Null" usw.
Also, IMHO, muss null ein kritischer Fehler sein, der eine weitere Ausführung verhindert (dh wenn null kein gültiger Wert ist).
Ich löse dieses Problem folgendermaßen:
Zunächst folge ich dieser Konvention:
Und schließlich lautet die erste Zeile der öffentlichen Methode im Code wie folgt:
Beachten Sie, dass addParam () self zurückgibt, sodass Sie weitere zu überprüfende Parameter hinzufügen können.
Die Methode
validate()
wird aktiviert,ValidationException
wenn einer der Parameter null ist (aktiviert oder deaktiviert ist eher ein Design- / Geschmacksproblem, aber myValidationException
ist aktiviert).Die Nachricht enthält den folgenden Text, wenn beispielsweise "Pläne" null ist:
" Für Parameter [Pläne] wird der unzulässige Argumentwert null gefunden. "
Wie Sie sehen, wird der zweite Wert in der Methode addParam () (Zeichenfolge) für die Benutzernachricht benötigt, da Sie den Namen der übergebenen Variablen auch bei Reflexion nicht leicht erkennen können (ohnehin nicht Gegenstand dieses Beitrags ...).
Und ja, wir wissen, dass wir jenseits dieser Zeile keinen Nullwert mehr finden, also rufen wir einfach sicher Methoden für diese Objekte auf.
Auf diese Weise ist der Code sauber, leicht zu warten und lesbar.
quelle
Das Stellen dieser Frage weist darauf hin, dass Sie möglicherweise an Strategien zur Fehlerbehandlung interessiert sind. Der Architekt Ihres Teams sollte entscheiden, wie Fehler behoben werden sollen. Es gibt verschiedene Möglichkeiten, dies zu tun:
Lassen Sie die Ausnahmen durchlaufen - fangen Sie sie an der Hauptschleife oder in einer anderen Verwaltungsroutine ab.
Schauen Sie sich auch die aspektorientierte Programmierung an - sie bietet eine gute Möglichkeit, sie
if( o == null ) handleNull()
in Ihren Bytecode einzufügen .quelle
Zusätzlich zur Verwendung können
assert
Sie Folgendes verwenden:Das ist etwas besser als:
quelle
if (!something) { x(); } else { y(); }
würde, wäre ich geneigt, es so umzugestaltenif (something) { y(); } else { x(); }
(obwohl man argumentieren könnte, dass dies!= null
die positivere Option ist ...). Noch wichtiger ist jedoch, dass der wichtige Teil des Codes nicht in{}
s eingeschlossen ist und Sie für den größten Teil der Methode eine Ebene weniger Einrückung haben. Ich weiß nicht, ob das die Argumentation von fastcodejava war, aber das wäre meine.Verwenden Sie niemals null. Erlaube es nicht.
In meinen Klassen haben die meisten Felder und lokalen Variablen Standardwerte ungleich Null, und ich füge überall im Code Vertragsanweisungen (Always-On-Asserts) hinzu, um sicherzustellen, dass dies erzwungen wird (da es prägnanter und aussagekräftiger ist, als es zuzulassen als NPE auftauchen und dann die Zeilennummer auflösen müssen usw.).
Als ich diese Praxis übernahm, bemerkte ich, dass sich die Probleme von selbst zu beheben schienen. Sie würden die Dinge viel früher im Entwicklungsprozess zufällig erfassen und feststellen, dass Sie eine Schwachstelle hatten. Und was noch wichtiger ist. Es hilft, die Bedenken verschiedener Module zusammenzufassen, verschiedene Module können sich gegenseitig vertrauen und die Abfälle nicht mehr verunreinigen Code mit
if = null else
Konstrukten!Dies ist eine defensive Programmierung und führt auf lange Sicht zu viel saubererem Code. Bereinigen Sie die Daten immer, z. B. hier, indem Sie strenge Standards durchsetzen, und die Probleme verschwinden.
Die Verträge sind wie Mini-Unit-Tests, die auch in der Produktion immer laufen, und wenn die Dinge versagen, wissen Sie warum, und nicht eine zufällige NPE, die Sie irgendwie herausfinden müssen.
quelle
Guava, eine sehr nützliche Kernbibliothek von Google, verfügt über eine nette und nützliche API, um Nullen zu vermeiden. Ich finde UsingAndAvoidingNullExplained sehr hilfreich.
Wie im Wiki erklärt:
Verwendungszweck:
quelle
Dies ist ein sehr häufiges Problem für jeden Java-Entwickler. Daher gibt es in Java 8 offizielle Unterstützung, um diese Probleme ohne überfüllten Code zu beheben.
Java 8 wurde eingeführt
java.util.Optional<T>
. Es ist ein Container, der einen Wert ungleich Null enthalten kann oder nicht. Java 8 bietet eine sicherere Möglichkeit, ein Objekt zu behandeln, dessen Wert in einigen Fällen null sein kann. Es ist inspiriert von den Ideen von Haskell und Scala .Kurz gesagt, die optionale Klasse enthält Methoden, um Fälle explizit zu behandeln, in denen ein Wert vorhanden ist oder fehlt. Der Vorteil gegenüber Nullreferenzen besteht jedoch darin, dass die Optionale <T> -Klasse Sie dazu zwingt, über den Fall nachzudenken, in dem der Wert nicht vorhanden ist. Infolgedessen können Sie unbeabsichtigte Nullzeigerausnahmen verhindern.
Im obigen Beispiel haben wir eine Home-Service-Factory, die einen Handle an mehrere im Haus verfügbare Geräte zurückgibt. Diese Dienste können jedoch verfügbar / funktionsfähig sein oder nicht. Dies bedeutet, dass dies zu einer NullPointerException führen kann. Anstatt eine Nullbedingung hinzuzufügen
if
, bevor Sie einen Dienst verwenden, fügen wir sie in Optional <Service> ein.WRAPPING TO OPTION <T>
Betrachten wir eine Methode, um eine Referenz eines Dienstes von einer Fabrik zu erhalten. Anstatt die Servicereferenz zurückzugeben, schließen Sie sie mit Optional ein. Es informiert den API-Benutzer darüber, dass der zurückgegebene Dienst möglicherweise verfügbar / funktionsfähig ist oder nicht
Wie du siehst
Optional.ofNullable()
bietet dies eine einfache Möglichkeit, die Referenz zu verpacken. Es gibt andere Möglichkeiten, um die Referenz von Optional zu erhalten, entwederOptional.empty()
&Optional.of()
. Eine zum Zurückgeben eines leeren Objekts anstelle der Neuabstimmung von null und die andere zum Umschließen eines nicht nullbaren Objekts.WIE GENAU HILFT ES, EINEN NULL-CHECK ZU VERMEIDEN?
Sobald Sie ein Referenzobjekt umbrochen haben, bietet Optional viele nützliche Methoden zum Aufrufen von Methoden für eine umschlossene Referenz ohne NPE.
Optional.ifPresent ruft den angegebenen Consumer mit einer Referenz auf, wenn es sich um einen Wert ungleich Null handelt. Ansonsten macht es nichts.
Stellt eine Operation dar, die ein einzelnes Eingabeargument akzeptiert und kein Ergebnis zurückgibt. Im Gegensatz zu den meisten anderen funktionalen Schnittstellen wird erwartet, dass der Verbraucher über Nebenwirkungen arbeitet. Es ist so sauber und leicht zu verstehen. Im obigen Codebeispiel
HomeService.switchOn(Service)
wird aufgerufen, wenn die optionale Haltereferenz nicht Null ist.Wir verwenden den ternären Operator sehr oft, um die Nullbedingung zu überprüfen und einen alternativen Wert oder Standardwert zurückzugeben. Optional bietet eine andere Möglichkeit, dieselbe Bedingung zu behandeln, ohne null zu aktivieren. Optional.orElse (defaultObj) gibt defaultObj zurück, wenn das Optionale einen Nullwert hat. Verwenden wir dies in unserem Beispielcode:
Jetzt macht HomeServices.get () dasselbe, aber besser. Es wird geprüft, ob der Dienst bereits initialisiert ist oder nicht. Wenn dies der Fall ist, geben Sie dasselbe zurück oder erstellen Sie einen neuen neuen Dienst. Optional <T> .orElse (T) hilft, einen Standardwert zurückzugeben.
Schließlich ist hier unser NPE sowie null check-free Code:
Der komplette Beitrag ist NPE sowie null check-free Code… Wirklich? .
quelle
if(homeServices != null) {
die in geändert werden kannhomeServices.ifPresent(h -> //action)
.Ich mag Artikel von Nat Pryce. Hier sind die Links:
In den Artikeln gibt es auch einen Link zu einem Git-Repository für einen Java-Typ, den ich interessant finde, aber ich denke nicht, dass dies allein das Aufblähen des Prüfcodes verringern könnte. Nach einigen Recherchen im Internet denke ich ! = Null Code Bloat könnte hauptsächlich durch sorgfältiges Design verringert werden.
quelle
Ich habe das versucht
NullObjectPattern
aber für mich ist es nicht immer der beste Weg. Es gibt manchmal Fälle, in denen eine "keine Aktion" nicht angemessen ist.NullPointerException
ist eine Laufzeitausnahme , die bedeutet, dass der Entwickler schuld ist und mit genügend Erfahrung genau sagt, wo der Fehler liegt.Nun zur Antwort:
Versuchen Sie, alle Ihre Attribute und deren Zugriffsmethoden so privat wie möglich zu gestalten, oder vermeiden Sie es, sie den Clients zugänglich zu machen. Sie können die Argumentwerte natürlich im Konstruktor haben, aber wenn Sie den Bereich reduzieren, lassen Sie die Client-Klasse keinen ungültigen Wert übergeben. Wenn Sie die Werte ändern müssen, können Sie jederzeit neue erstellen
object
. Sie überprüfen die Werte im Konstruktor nur einmal und in den übrigen Methoden können Sie fast sicher sein, dass die Werte nicht null sind.Erfahrung ist natürlich der bessere Weg, diesen Vorschlag zu verstehen und anzuwenden.
Byte!
quelle
Die wahrscheinlich beste Alternative für Java 8 oder höher ist die Verwendung der
Optional
Klasse.Dies ist besonders praktisch für lange Ketten möglicher Nullwerte. Beispiel:
Beispiel, wie eine Ausnahme auf null ausgelöst wird:
Java 7 führte die
Objects.requireNonNull
Methode ein, die nützlich sein kann, wenn etwas auf Nicht-Nullheit überprüft werden soll. Beispiel:quelle
Darf ich allgemeiner antworten!
Wir normalerweise stellen diese Frage , wenn die Methoden , um die Parameter in die Quere kommen wir nicht zu erwarten (schlechte Methodenaufruf ist Fehler des Programmierers). Beispiel: Sie erwarten ein Objekt, stattdessen eine Null. Sie erwarten einen String mit mindestens einem Zeichen, stattdessen erhalten Sie einen leeren String ...
Es gibt also keinen Unterschied zwischen:
}}
oder
Beide möchten sicherstellen, dass wir gültige Parameter erhalten haben, bevor wir andere Funktionen ausführen.
Wie in einigen anderen Antworten erwähnt, können Sie, um die oben genannten Probleme zu vermeiden, dem Muster " Entwurf nach Vertrag" folgen . Weitere Informationen finden Sie unter http://en.wikipedia.org/wiki/Design_by_contract .
Um dieses Muster in Java zu implementieren, können Sie Java- Kernanmerkungen wie javax.annotation.NotNull verwenden oder Bibliotheken wie Hibernate Validator verwenden .
Nur ein Beispiel:
Jetzt können Sie die Kernfunktion Ihrer Methode sicher entwickeln, ohne die Eingabeparameter überprüfen zu müssen. Sie schützen Ihre Methoden vor unerwarteten Parametern.
Sie können noch einen Schritt weiter gehen und sicherstellen, dass in Ihrer Anwendung nur gültige Pojos erstellt werden können. (Beispiel von der Validator-Site im Ruhezustand)
quelle
javax
ist per Definition nicht "Core Java".Ich ignoriere Antworten, die vorschlagen, in jeder Situation die Nullobjekte zu verwenden. Dieses Muster kann den Vertrag brechen und Probleme immer tiefer begraben, anstatt sie zu lösen. Ganz zu schweigen davon, dass bei unsachgemäßer Verwendung ein weiterer Stapel Code für die Kesselplatte entsteht, der künftig gewartet werden muss.
Wenn in der Realität etwas, das von einer Methode zurückgegeben wird, null sein kann und der aufrufende Code darüber entscheiden muss, sollte es einen früheren Aufruf geben, der den Status sicherstellt.
Denken Sie auch daran, dass das Nullobjektmuster speicherhungrig ist, wenn es ohne Sorgfalt verwendet wird. Aus diesem Grund sollte die Instanz eines NullObjects von den Eigentümern gemeinsam genutzt werden und nicht für jede dieser Instanzen eine eindeutige Instanz sein.
Ich würde auch nicht empfehlen, dieses Muster zu verwenden, wenn der Typ eine primitive Typdarstellung sein soll - wie mathematische Entitäten, die keine Skalare sind: Vektoren, Matrizen, komplexe Zahlen und POD-Objekte (Plain Old Data), die den Status halten sollen in Form von Java integrierten Typen. Im letzteren Fall würden Sie am Ende Getter-Methoden mit beliebigen Ergebnissen aufrufen. Was sollte beispielsweise eine NullPerson.getName () -Methode zurückgeben?
Es lohnt sich, solche Fälle in Betracht zu ziehen, um absurde Ergebnisse zu vermeiden.
quelle
Wenn Sie dies in Ihrem eigenen Code tun, können Sie! = Null-Überprüfungen vermeiden.
Meistens scheinen Nullprüfungen Schleifen über Sammlungen oder Arrays zu schützen. Initialisieren Sie sie also einfach leer, Sie benötigen keine Nullprüfungen.
Das ist ein winziger Aufwand, aber es lohnt sich für saubereren Code und weniger NullPointerExceptions.
quelle
Dies ist der häufigste Fehler, der bei den meisten Entwicklern aufgetreten ist.
Wir haben verschiedene Möglichkeiten, damit umzugehen.
Ansatz 1:
notNull (Objektobjekt, String-Nachricht)
Ansatz 2:
Ansatz 3:
Ansatz 4:
quelle
quelle
ObjectUtils.defaultIfNull()
. Es gibt noch eine allgemeinere :ObjectUtils.firstNonNull()
, die verwendet werden kann, um eine erniedrigende Strategie umzusetzen:firstNonNull(bestChoice, secondBest, thirdBest, fallBack);