Vermeiden! = Null-Anweisungen

4014

Ich benutze object != nullviel, 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 NullPointerExceptionfür das someobjectObjekt.

Beachten Sie, dass die akzeptierte Antwort möglicherweise veraltet ist. Weitere Informationen finden Sie unter https://stackoverflow.com/a/2386013/12943 .

Goran Martinic
quelle
120
@Shervin Durch die Förderung von Nullen wird der Code weniger verständlich und weniger zuverlässig.
Tom Hawtin - Tackline
44
Die Elvis-Operatoren wurden vorgeschlagen, aber es sieht so aus, als würde es nicht in Java 7 sein . Schade, ?. ?: und? [] sparen unglaublich viel Zeit.
Scott
72
Die Nichtverwendung von null ist den meisten anderen Vorschlägen hier überlegen. Ausnahmen auslösen, keine Nullen zurückgeben oder zulassen. Übrigens - das Schlüsselwort 'assert' ist nutzlos, da es standardmäßig deaktiviert ist. Verwenden Sie einen immer aktivierten Fehlermechanismus
ianpojman
13
Dies ist ein Grund, warum ich jetzt Scala benutze. In Scala ist nicht alles nullwertfähig. Wenn Sie zulassen möchten, dass "nichts" übergeben oder zurückgegeben wird, müssen Sie ausdrücklich Option [T] anstelle von nur T als Argument oder Rückgabetyp verwenden.
Thekwasti
11
@thSoft In der Tat wird Scalas großartiger OptionTyp durch die mangelnde Bereitschaft der Sprache beeinträchtigt, zu kontrollieren oder zu verbieten null. 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 das
Andres F.

Antworten:

2642

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:

  1. Wenn null eine gültige vertragliche Antwort ist; und

  2. Wo es keine gültige Antwort ist.

(2) ist einfach. Verwenden Sie entweder assertAnweisungen (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:

assert <condition>

oder

assert <condition> : <object>

Dabei <condition>handelt es sich um einen booleschen Ausdruck und <object>um ein Objekt, dessen toString()Methodenausgabe in den Fehler einbezogen wird.

Eine assertAnweisung löst ein Error( AssertionError) aus, wenn die Bedingung nicht erfüllt ist. Standardmäßig ignoriert Java Zusicherungen. Sie können Zusicherungen aktivieren, indem Sie die Option -eaan 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:

public interface Action {
  void doSomething();
}

public interface Parser {
  Action findAction(String userInput);
}

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 :

public class MyParser implements Parser {
  private static Action DO_NOTHING = new Action() {
    public void doSomething() { /* do nothing */ }
  };

  public Action findAction(String userInput) {
    // ...
    if ( /* we can't find any actions */ ) {
      return DO_NOTHING;
    }
  }
}

Vergleichen Sie:

Parser parser = ParserFactory.getParser();
if (parser == null) {
  // now what?
  // this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
  // do nothing
} else {
  action.doSomething();
}

zu

ParserFactory.getParser().findAction(someInput).doSomething();

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.

try {
    ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
    userConsole.err(anfe.getMessage());
}

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.

public Action findAction(final String userInput) {
    /* Code to return requested Action if found */
    return new Action() {
        public void doSomething() {
            userConsole.err("Action not found: " + userInput);
        }
    }
}
Cletus
quelle
631
Ich bin mit Ihren Aussagen für die Aktion DO_NOTHING nicht einverstanden. Wenn die Methode find action keine Aktion finden kann, ist es richtig, null zurückzugeben. Sie haben eine Aktion in Ihrem Code "gefunden", die nicht wirklich gefunden wurde und gegen das Prinzip der Methode verstößt, um eine verwendbare Aktion zu finden.
MetroidFan2002
266
Ich bin damit einverstanden, dass null in Java überbeansprucht wird, insbesondere bei Listen. So viele Apis wären besser, wenn sie eine leere Liste / Array / Sammlung anstelle von Null zurückgeben würden. Oft wird null verwendet, wenn stattdessen eine Ausnahme ausgelöst werden soll. Eine Ausnahme sollte ausgelöst werden, wenn der Parser nicht analysieren kann.
Laplie Anderson
92
Das letztere Beispiel hier ist IIRC, das Nullobjekt-Entwurfsmuster.
Steven Evers
62
@Cshah (und MetroidFan2002). Einfach, setzen Sie das in den Vertrag ein und dann ist klar, dass eine nicht gefundene zurückgegebene Aktion nichts bewirkt. Wenn dies wichtige Informationen für den Aufrufer sind, geben Sie eine Möglichkeit an, festzustellen, dass es sich um eine nicht gefundene Aktion handelt (dh geben Sie eine Methode an, um zu überprüfen, ob das Ergebnis das Objekt DO_NOTHING war). Wenn normalerweise eine Aktion gefunden werden sollte, sollten Sie dennoch nicht null zurückgeben, sondern eine Ausnahme auslösen, die speziell auf diese Bedingung hinweist - dies führt immer noch zu besserem Code. Geben Sie bei Bedarf eine separate Methode an, die einen Booleschen Wert zurückgibt, um zu überprüfen, ob eine Aktion vorhanden ist.
Kevin Brock
35
Prägnant ist nicht gleich Qualitätscode. Es tut mir leid, dass du das denkst. Ihr Code verbirgt Situationen, in denen ein Fehler von Vorteil wäre.
Gshauger
635

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 @Nullableund @NotNull.

Sie können in Methode und Parametern wie folgt verwenden:

@NotNull public static String helloWorld() {
    return "Hello World";
}

oder

@Nullable public static String helloWorld() {
    return "Hello World";
}

Das zweite Beispiel wird nicht kompiliert (in IntelliJ IDEA).

Wenn Sie die erste helloWorld()Funktion in einem anderen Code verwenden:

public static void main(String[] args)
{
    String result = helloWorld();
    if(result != null) {
        System.out.println(result);
    }
}

Jetzt teilt Ihnen der IntelliJ IDEA-Compiler mit, dass die Prüfung nutzlos ist, da die helloWorld()Funktion nullniemals zurückkehren wird.

Parameter verwenden

void someMethod(@NotNull someParameter) { }

wenn du so etwas schreibst wie:

someMethod(null);

Dies wird nicht kompiliert.

Letztes Beispiel mit @Nullable

@Nullable iWantToDestroyEverything() { return null; }

Dies tun

iWantToDestroyEverything().something();

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 @NotNullImplementierungen hinzugefügt .

Siehe Blog-Beitrag Flexiblere und konfigurierbarere @ Nullable / @ NotNull-Anmerkungen .

Luca Molteni
quelle
120
@NotNull, @NullableUnd andere nullness Anmerkungen sind Bestandteil von JSR 305 . Sie können sie auch verwenden, um potenzielle Probleme mit Tools wie FindBugs zu erkennen .
Jacek S
32
Ich finde es seltsam ärgerlich, dass die @NotNull& @NullableSchnittstellen im Paket leben com.sun.istack.internal. (Ich glaube, ich verbinde com.sun mit Warnungen über die Verwendung einer proprietären API.)
Jonik
20
Code-Portabilität wird bei Jetbrains null. Ich würde zweimal überlegen (quadratisch), bevor ich mich auf die Ide-Ebene einbinde. Wie Jacek S sagte, dass sie in jeder Hinsicht Teil von JSR sind, was ich übrigens für JSR303 hielt.
Java Ka Baby
10
Ich denke wirklich nicht, dass die Verwendung eines benutzerdefinierten Compilers eine praktikable Lösung für dieses Problem ist.
Shivan Dragon
64
Die gute Sache über Annotationen, die @NotNullund @Nullablesind 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 ;-)
amn
321

Wenn Nullwerte nicht erlaubt sind

Wenn Ihre Methode extern aufgerufen wird, beginnen Sie mit Folgendes:

public void method(Object object) {
  if (object == null) {
    throw new IllegalArgumentException("...");
  }

Im Rest dieser Methode wissen Sie dann, dass dies objectnicht 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:

public String getFirst3Chars(String text) {
  return text.subString(0, 3);
}

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:

if (object == null) {
  // something
} else {
  // something else
}

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.

myplacedk
quelle
94
Was bringt es, IllegalArgumentException auszulösen? Ich denke, NullPointerException wäre klarer, und das würde auch ausgelöst, wenn Sie die Nullprüfung nicht selbst durchführen. Ich würde entweder assert oder gar nichts verwenden.
Axel
23
Es ist unwahrscheinlich, dass jeder andere Wert als null akzeptabel ist. Sie könnten IllegalArgumentException, OutOfRageException usw. usw. haben. Manchmal ist dies sinnvoll. In anderen Fällen erstellen Sie am Ende viele Ausnahmeklassen, die keinen Wert hinzufügen. Dann verwenden Sie einfach IllegalArgumentException. Es ist nicht sinnvoll, eine Ausnahme für die Null-Eingabe und eine andere für alles andere zu haben.
Myplacedk
7
Ja, ich stimme dem Fail-Fast-Prinzip zu, aber im obigen Beispiel wird der Wert nicht weitergegeben, sondern ist das Objekt, für das eine Methode aufgerufen werden soll. Es schlägt also genauso schnell fehl, und das Hinzufügen einer Nullprüfung, um eine Ausnahme auszulösen, die ohnehin zur gleichen Zeit und am gleichen Ort ausgelöst wird, scheint das Debuggen nicht einfacher zu machen.
Axel
8
Eine Sicherheitslücke? Das JDK ist voll von Code wie diesem. Wenn der Benutzer keine Stacktraces sehen soll, deaktivieren Sie diese einfach. Niemand hat angedeutet, dass das Verhalten nicht dokumentiert ist. MySQL ist in C geschrieben, wo das Dereferenzieren von Nullzeigern ein undefiniertes Verhalten ist, nichts wie das Auslösen einer Ausnahme.
FGB
8
throw new IllegalArgumentException("object==null")
Thorbjørn Ravn Andersen
238

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:

public String getPostcode(Person person) {  
  return person?.getAddress()?.getPostcode();  
}  

Das ?.Mittel de-referenziert den linken Bezeichner nur, wenn er nicht null ist, andernfalls wird der Rest des Ausdrucks als ausgewertet null. 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 Verwendung nullals 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.

erickson
quelle
20
Ich denke das ist falsch. Es sollte eine Möglichkeit geben, anzugeben, dass eine bestimmte Variable IMMER nicht null ist.
Thorbjørn Ravn Andersen
5
Update: Der Vorschlag macht kein Java7. Siehe blogs.sun.com/darcy/entry/project_coin_final_five .
Boris Terzic
9
Interessante Idee, aber die Wahl der Syntax ist absurd; Ich möchte nicht, dass in jedem Joint eine Codebasis voller Fragezeichen steckt.
Rob
7
Dieser Operator ist in Groovy vorhanden , sodass diejenigen, die ihn verwenden möchten, diesen weiterhin als Option haben.
Muhd
8
Dies ist die genialste Idee, die ich je gesehen habe. Es sollte zu jeder sinnvollen Sprache der C-Syntax hinzugefügt werden. Ich würde lieber überall "Fragezeichen anheften", als den ganzen Tag durch eine Reihe von Zeilen zu scrollen oder "Schutzklauseln" auszuweichen.
Victor
196

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:

  • In der API wird explizit angegeben, ob eine Eingabe oder Ausgabe vorhanden ist oder nicht.
  • Der Compiler zwingt Sie, den "undefinierten" Fall zu behandeln.
  • Option ist eine Monade , daher ist keine ausführliche Nullprüfung erforderlich. Verwenden Sie einfach map / foreach / getOrElse oder einen ähnlichen Kombinator, um den Wert sicher zu verwenden (Beispiel) .

Java 8 verfügt über eine integrierte OptionalKlasse (empfohlen). für frühere Versionen gibt es Bibliothek Alternativen, zum Beispiel Guava ‚s Optionaloder FunctionalJava ‘ s Option. 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.

thSoft
quelle
22
In der Tat ist das Optionsmuster fantastisch. Es gibt einige Java-Entsprechungen. Guava enthält eine limitierte Version davon namens Optional, bei der die meisten funktionalen Dinge weggelassen werden. In Haskell heißt dieses Muster Vielleicht.
Ben Hardy
9
Eine optionale Klasse wird in Java 8 verfügbar sein
Pierre Henry
1
... und es hat (noch) keine Karte oder flatMap: download.java.net/jdk8/docs/api/java/util/Optional.html
thSoft
3
Das optionale Muster löst nichts. Anstelle eines potenziell null Objekts haben Sie jetzt zwei.
Boann
1
@Boann, wenn Sie mit Sorgfalt verwendet werden, lösen Sie alle Ihre NPEs Problem. Wenn nicht, dann gibt es vermutlich ein "Verwendungsproblem".
Louis F.
189

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

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

führt zu einem NullPointerExceptionwenn foonicht existiert.

Sie können dies vermeiden, wenn Sie Ihre Strings wie folgt vergleichen :

if ( "bar".equals(foo) ) {
 // ...
}
Echox
quelle
42
Ich stimme zu - nur in dieser Situation. Ich kann Programmierer nicht leiden, die dies auf die nächste unnötige Ebene gebracht haben und schreiben, wenn (null! = MyVar) ... für mich nur hässlich aussieht und keinen Zweck erfüllt!
Alex Worden
20
Dies ist ein besonderes, wahrscheinlich am häufigsten verwendetes Beispiel für eine allgemeine bewährte Methode: Wenn Sie es wissen, tun Sie es immer <object that you know that is not null>.equals(<object that might be null>);. Es funktioniert für andere Methoden als equalswenn Sie den Vertrag kennen und diese Methoden nullParameter verarbeiten können.
Stef
9
Dies ist das erste Beispiel, das ich von Yoda Conditions gesehen habe , das tatsächlich Sinn macht
Erin Drummond
6
NullPointerExceptions werden aus einem bestimmten Grund ausgelöst. Sie werden ausgelöst, weil ein Objekt null ist, wo es nicht sein sollte. Es ist die Aufgabe des Programmierers, dies zu beheben, nicht das Problem zu verbergen.
Oliver Watkins
1
Try-Catch-DoNothing verbirgt das Problem. Dies ist eine gültige Vorgehensweise, um fehlenden Zucker in der Sprache zu umgehen.
Echox
167

Mit Java 8 kommt die neue java.util.OptionalKlasse, 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 ein FruitObjekt enthalten :

public static Optional<Fruit> find(String name, List<Fruit> fruits) {
   for (Fruit fruit : fruits) {
      if (fruit.getName().equals(name)) {
         return Optional.of(fruit);
      }
   }
   return Optional.empty();
}

Schauen Sie sich nun diesen Code an, in dem wir eine Liste von Fruit( fruits) nach einer bestimmten Fruit-Instanz durchsuchen :

Optional<Fruit> found = find("lemon", fruits);
if (found.isPresent()) {
   Fruit fruit = found.get();
   String name = fruit.getName();
}

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.

String nameOrNull = find("lemon", fruits)
    .map(f -> f.getName())
    .orElse("empty-name");

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, Optionalbei der ein Rückgabewert möglicherweise leer ist und ein einfaches Objekt nur dann zurückgegeben wird, wenn dies nicht möglich ist null(Konvention), gibt der Clientcode möglicherweise Nullprüfungen für einfache Objektrückgabewerte auf ...

Natürlich Optionalkönnte es auch als Methodenargument verwendet werden, vielleicht eine bessere Möglichkeit, optionale Argumente anzugeben, als in einigen Fällen 5 oder 10 Überladungsmethoden.

Optionalbietet andere bequeme Methoden, z. B. orElsedie die Verwendung eines Standardwerts ermöglichen und ifPresentmit 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, Optionalgut erklärt werden: Java Optional Objects .

Pierre Henry
quelle
11
Googles Guave hat eine optionale Implementierung für Java 6+.
Bradley Gottfried
13
Es ist sehr wichtig , dass mit ifPresent nur mit optional zu betonen () gibt nicht viel Wert über dem normalen Nullprüfung hinzufügen. Der Kernwert besteht darin, dass es sich um eine Monade handelt, die in Funktionsketten von map / flapMap verwendet werden kann und ähnliche Ergebnisse wie der an anderer Stelle erwähnte Elvis-Operator in Groovy erzielt. Auch ohne diese Verwendung finde ich die orElse / orElseThrow-Syntax ebenfalls sehr nützlich.
Cornel Masson
Dieser Blog hat einen guten Eintrag auf Optional winterbe.com/posts/2015/03/15/avoid-null-checks-in-java
JohnC
4
Warum Menschen haben die Tendenz , dies zu tun , if(optional.isPresent()){ optional.get(); }anstattoptional.ifPresent(o -> { ...})
Satyendra Kumar
1
Abgesehen von den vertraglichen Hinweisen zur API geht es also wirklich nur darum, funktionale Programmierer zu bedienen, die endlose Verkettungsmethoden genießen.
Crush
125

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:

String foo;
...
if( StringUtils.isBlank( foo ) ) {
   ///do something
}

oder (je nachdem, was Sie überprüfen müssen):

String foo;
...
if( StringUtils.isEmpty( foo ) ) {
   ///do something
}

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.

public DOCUMENT read(String xml, ValidationEventHandler validationEventHandler) {
    Validate.notNull(validationEventHandler,"ValidationHandler not Injected");
    return read(new StringReader(xml), true, validationEventHandler);
}

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)

Assert.notNull(validationEventHandler,"ValidationHandler not Injected");
javamonkey79
quelle
5
Sie können auch die allgemeinere Version von Apache Commons verwenden, die zu Beginn der Methoden sehr nützlich ist, um die von mir gefundenen Parameter zu überprüfen. Validate.notNull (Objekt, "Objekt darf nicht null sein"); commons.apache.org/lang/apidocs/org/apache/commons/lang/…
Monojohnny
@monojohnny verwendet Validate Assert-Anweisungen in?. Ich bitte darum, weil Assert auf JVM aktiviert / deaktiviert sein kann und es empfohlen wird, es nicht in der Produktion zu verwenden.
Kurapika
Denken Sie nicht so - ich glaube, es löst nur eine RuntimeException aus, wenn die Validierung fehlschlägt
Monojohnny
96
  • Wenn Sie der Meinung sind, dass ein Objekt nicht null sein sollte (oder es sich um einen Fehler handelt), verwenden Sie eine Zusicherung.
  • Wenn Ihre Methode keine Nullparameter akzeptiert, sagen Sie dies im Javadoc und verwenden Sie eine Zusicherung.

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

pgras
quelle
3
Nein, verwenden Sie keine Zusicherungen im Produktionscode .
Phil294
91

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.

Alex Worden
quelle
2
Es ist besser, Assertions zu verwenden, dh Contract.notNull (abc, "abc muss nicht null sein, konnte es während xyz nicht geladen werden?"); - Dies ist eine kompaktere Methode als eine if (abc! = Null) {neue RuntimeException auslösen ...}
ianpojman
76

Das Google-Sammlungsframework bietet eine gute und elegante Möglichkeit, die Nullprüfung durchzuführen.

In einer Bibliotheksklasse wie dieser gibt es eine Methode:

static <T> T checkNotNull(T e) {
   if (e == null) {
      throw new NullPointerException();
   }
   return e;
}

Und die Verwendung ist (mit import static):

...
void foo(int a, Person p) {
   if (checkNotNull(p).getAge() > a) {
      ...
   }
   else {
      ...
   }
}
...

Oder in Ihrem Beispiel:

checkNotNull(someobject).doCalc();
Benutzer2427
quelle
71
mmm, was ist der Unterschied? p.getAge () würde dieselbe NPE mit weniger Overhead und einer klareren Stapelverfolgung auslösen. Was vermisse ich?
Mysomic
15
Es ist besser, in Ihrem Beispiel eine IllegalArgumentException ("e == null") auszulösen, da dies eindeutig darauf hinweist, dass es sich um eine vom Programmierer beabsichtigte Ausnahme handelt (zusammen mit genügend Informationen, damit der Betreuer das Problem tatsächlich identifizieren kann). NullPointerExceptions sollten für die JVM reserviert werden, da dies eindeutig anzeigt, dass dies unbeabsichtigt war (und normalerweise an einem schwer zu identifizierenden Ort geschieht)
Thorbjørn Ravn Andersen
6
Dies ist jetzt Teil von Google Guava.
Steven Benitez
32
Riecht für mich nach Überentwicklung. Lassen Sie einfach die JVM eine NPE werfen und überladen Sie Ihren Code nicht mit diesem Müll.
Alex Worden
5
Ich mag es und öffne die meisten Methoden und Konstruktoren mit expliziten Überprüfungen der Argumente; Wenn es einen Fehler gibt, schlagen Methoden immer in den ersten Zeilen fehl und ich kenne die beleidigende Referenz, ohne etwas zu finden wiegetThing().getItsThing().getOtherThing().wowEncapsulationIsBroken().setLol("hi");
Cory Kendall
75

Manchmal haben Sie Methoden, die mit ihren Parametern arbeiten, die eine symmetrische Operation definieren:

a.f(b); <-> b.f(a);

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

Johannes Schaub - litb
quelle
2
Aber dann müssen Sie davon ausgehen 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.
Supericy
4
@ Supericy Grundsätzlich ja, aber equals(oder welche Methode auch immer) muss nullsowieso nachsehen . Oder geben Sie ausdrücklich an, dass dies nicht der Fall ist.
Angelo Fuchs
74

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.

Jim Nelson
quelle
17
Das Problem ist, dass Sie normalerweise den Kontext verlieren, da die NullPointerException nicht angibt, welche Variable null war, und Sie möglicherweise mehrere "." - Operationen in der Zeile haben. Wenn Sie "if (foo == null) throw new RuntimeException (" foo == null ")" verwenden, können Sie explizit angeben, WAS falsch war, und Ihren Stack-Trace für diejenigen, die das Problem beheben müssen, wesentlich wertvoller machen.
Thorbjørn Ravn Andersen
1
Mit Andersen - Ich würde es lieben, wenn das Ausnahmesystem von Java den Namen einer Variablen enthalten könnte, an der gearbeitet wird, sodass NullPointerExceptions nicht nur die Zeile angibt, in der die Ausnahme aufgetreten ist, sondern auch den Variablennamen. Dies sollte in unverhohlener Software einwandfrei funktionieren.
Fwielstra
Ich habe es noch nicht geschafft, es zum Laufen zu bringen, aber dies soll genau dieses Problem lösen.
MatrixFrog
Was ist das Problem? Fangen Sie einfach die NPE auf der entsprechenden Ebene ab, auf der genügend Kontext verfügbar ist, sichern Sie die Kontextinformationen und werfen Sie die Ausnahme erneut ... mit Java ist das so einfach.
user1050755
3
Ich hatte einen Professor, der gegen die Verkettung von Methodenaufrufen predigte. Seine Theorie war, dass Sie sich vor Anrufketten hüten sollten, die länger als zwei Methoden waren. Ich weiß nicht, ob das eine harte Regel ist, aber sie beseitigt definitiv die meisten Probleme mit NPE-Stack-Traces.
RustyTheBoyRobot
74

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)

  1. 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.

    public Photo getPhotoOfThePerson(Person person) {
        if (person == null)
            return null;
        // Grabbing some resources or intensive calculation
        // using person object anyhow.
    }

    Zurück führt zu einem normalen Logikfluss, um kein Foto einer nicht existierenden Freundin aus meiner Fotobibliothek zu erhalten.

    getPhotoOfThePerson(me.getGirlfriend())

    Und es passt zur neuen Java-API (mit Blick auf die Zukunft)

    getPhotoByName(me.getGirlfriend()?.getName())

    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

    public static MyEnum parseMyEnum(String value); // throws IllegalArgumentException
    public static MyEnum parseMyEnumOrNull(String value);

    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.

    /**
     * @return photo or null
     */

    oder

    /**
     * @return photo, never null
     */
  2. 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 NullPointerExceptionUnterklasse von Exception. Somit ist es eine Form Throwable, 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 fangen NullPointerException.

    public Photo getGirlfriendPhoto() {
        try {
            return appContext.getPhotoDataSource().getPhotoByName(me.getGirlfriend().getName());
        } catch (NullPointerException e) {
            return null;
        }
    }

    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, PreparedStatementden 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:

    public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
        try {
            Result1 result1 = performSomeCalculation(predicate);
            Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
            Result3 result3 = performThirdCalculation(result2.getSomeProperty());
            Result4 result4 = performLastCalculation(result3.getSomeProperty());
            return result4.getSomeProperty();
        } catch (NullPointerException e) {
            return null;
        }
    }
    
    public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
        SomeValue result = null;
        if (predicate != null) {
            Result1 result1 = performSomeCalculation(predicate);
            if (result1 != null && result1.getSomeProperty() != null) {
                Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
                if (result2 != null && result2.getSomeProperty() != null) {
                    Result3 result3 = performThirdCalculation(result2.getSomeProperty());
                    if (result3 != null && result3.getSomeProperty() != null) {
                        Result4 result4 = performLastCalculation(result3.getSomeProperty());
                        if (result4 != null) {
                            result = result4.getSomeProperty();
                        }
                    }
                }
            }
        }
        return result;
    }

    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 dem ThreadDeathes sich Errornicht um einen Anwendungsfehler handelt, sondern nur, weil er nicht abgefangen werden sollte! Wie viel NPE passt zu einem Errorals ThreadDeath! Aber es ist nicht.

  3. Suchen Sie nur dann nach "Keine Daten", wenn die Geschäftslogik dies impliziert.

    public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
        if (personId == null)
            return;
        DataSource dataSource = appContext.getStuffDataSource();
        Person person = dataSource.getPersonById(personId);
        if (person != null) {
            person.setPhoneNumber(phoneNumber);
            dataSource.updatePerson(person);
        } else {
            Person = new Person(personId);
            person.setPhoneNumber(phoneNumber);
            dataSource.insertPerson(person);
        }
    }

    und

    public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
        if (personId == null)
            return;
        DataSource dataSource = appContext.getStuffDataSource();
        Person person = dataSource.getPersonById(personId);
        if (person == null)
            throw new SomeReasonableUserException("What are you thinking about ???");
        person.setPhoneNumber(phoneNumber);
        dataSource.updatePerson(person);
    }

    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.

Mykhaylo Adamovych
quelle
6
Das Fangen NullPointerExceptionund Zurückkehren nullist schrecklich zu debuggen. Du landest sowieso später mit NPE und es ist wirklich schwer herauszufinden, was ursprünglich null war.
Artbristol
23
Ich würde abstimmen, wenn ich den Ruf hätte. Null ist nicht nur nicht notwendig, es ist auch ein Loch im Typensystem. Das Zuweisen eines Baums zu einer Liste ist ein Typfehler, da Bäume keine Werte vom Typ Liste sind. Nach derselben Logik sollte das Zuweisen von Null ein Typfehler sein, da Null kein Wert vom Typ Objekt oder ein nützlicher Typ für diese Angelegenheit ist. Sogar der Mann, der Null erfunden hat, betrachtet es als seinen "Milliarden-Dollar-Fehler". Der Begriff "ein Wert, der ein Wert vom Typ T ODER nichts sein kann" ist ein eigener Typ und sollte als solcher dargestellt werden (z. B. Vielleicht <T> oder Optional <T>).
Doval
2
Ab "Vielleicht <T> oder Optional <T>" müssen Sie noch Code schreiben, if (maybeNull.hasValue()) {...}also was ist der Unterschied zu if (maybeNull != null)) {...}?
Mykhaylo Adamovych
1
Ab "NullPointerException abzufangen und Null zurückzugeben ist schrecklich zu debuggen. Sie erhalten ohnehin später NPE, und es ist wirklich schwer herauszufinden, was ursprünglich Null war". Ich stimme total zu! In diesen Fällen sollten Sie ein Dutzend 'if'-Anweisungen schreiben oder NPE auslösen, wenn die Geschäftslogik Daten an Ort und Stelle impliziert, oder einen null-sicheren Operator aus neuem Java verwenden. Aber es gibt Fälle, in denen es mir egal ist, welcher genaue Schritt mir null gibt. Berechnen Sie beispielsweise einige Werte für den Benutzer, bevor Sie sie auf dem Bildschirm anzeigen, wenn Sie erwarten, dass Daten fehlen könnten.
Mykhaylo Adamovych
3
@MykhayloAdamovych: Der Vorteil von Maybe<T>oder Optional<T>nicht in dem Fall, in dem Sie Tmö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ückgeben T, können Sie davon ausgehen, dass er niemals null ist , wenn Sie in Ihrem Code einen einfachen alten Wert sehen . (
Natürlich
71

Java 7 verfügt über eine neue java.util.ObjectsDienstprogrammklasse, für die es eine requireNonNull()Methode gibt. Alles was dies tut ist ein a zu werfen, NullPointerExceptionwenn sein Argument null ist, aber es bereinigt den Code ein wenig. Beispiel:

Objects.requireNonNull(someObject);
someObject.doCalc();

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:

Parent(Child child) {
   if (child == null) {
      throw new NullPointerException("child");
   }
   this.child = child;
}

wird

Parent(Child child) {
   this.child = Objects.requireNonNull(child, "child");
}
Raedwald
quelle
9
Tatsächlich stellt Ihr Beispiel Code Bloat dar: Die erste Zeile ist überflüssig, da die NPE in die zweite Zeile geworfen würde. ;-)
user1050755
1
Wahr. Ein besseres Beispiel wäre, wenn die zweite Zeile wäre doCalc(someObject).
Stuart Marks
Hängt davon ab. Wenn Sie der Autor von doCalc () sind, würde ich vorschlagen, den Check in den Body dieser Methode einzufügen (falls möglich). Und dann rufen Sie höchstwahrscheinlich someObject.someMethod () auf, wo wiederum nicht nach null gesucht werden muss. :-)
user1050755
Nun, wenn Sie nicht der Autor von doCalc()sind und NPE nicht sofort ausgelöst wird, wenn null angegeben wird, müssen Sie nach null suchen und NPE selbst werfen. Dafür Objects.requireNonNull()ist es da.
Stuart Marks
7
Es ist nicht nur Code aufblähen. Es ist besser, im Voraus zu prüfen, als in der Mitte einer Methode, die Nebenwirkungen verursacht oder Zeit / Raum verwendet.
Rob Grant
51

Letztendlich ist die einzige Möglichkeit, dieses Problem vollständig zu lösen, die Verwendung einer anderen Programmiersprache:

  • In Objective-C können Sie das Äquivalent zum Aufrufen einer Methode ausführen nil, und es wird absolut nichts passieren. Dies macht die meisten Nullprüfungen unnötig, kann jedoch die Diagnose von Fehlern erheblich erschweren.
  • In Nizza , einer von Java abgeleiteten Sprache, gibt es zwei Versionen aller Art: eine Version mit potenziell null und eine Version ohne null. Sie können Methoden nur für Nicht-Null-Typen aufrufen. Potenziell Null-Typen können durch explizite Überprüfung auf Null in Nicht-Null-Typen konvertiert werden. Dies macht es viel einfacher zu wissen, wo Nullprüfungen erforderlich sind und wo nicht.
Michael Borgwardt
quelle
Woah ... Die richtigste Antwort und sie wird herabgestimmt, wo ist die Gerechtigkeit? In Java ist null immer ein gültiger Wert. Es ist die Folge von Alles ist ein Objekt - Null ist ein Alles (natürlich ignorieren wir hier Primitive, aber Sie haben die Idee). Persönlich bevorzuge ich den Ansatz von Nizza, obwohl wir ihn so gestalten könnten, dass Methoden für nullfähige Typen aufgerufen werden können und NPEs zu geprüften Ausnahmen befördert werden. Dies müsste jedoch über einen Compiler-Schalter erfolgen, da dadurch der gesamte vorhandene Code
beschädigt
4
Ich bin nicht mit Nizza vertraut, aber Kotlin implementiert die gleiche Idee, indem nullbare und nicht null Typen in das Typensystem der Sprache eingebaut werden. Viel prägnanter als Optionals oder Null-Objektmuster.
Mtsahakis
38

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:

  1. Alle öffentlichen Methoden / APIs überprüfen ihre Argumente immer auf null
  2. Alle privaten Methoden suchen nicht nach Null, da es sich um kontrollierte Methoden handelt (lassen Sie sie einfach mit der Nullzeiger-Ausnahme sterben, falls dies oben nicht behandelt wurde).
  3. Die einzigen anderen Methoden, die nicht auf Null prüfen, sind Dienstprogrammmethoden. Sie sind öffentlich, aber wenn Sie sie aus irgendeinem Grund aufrufen, wissen Sie, welche Parameter Sie übergeben. Dies ist wie der Versuch, Wasser im Wasserkocher zu kochen, ohne Wasser bereitzustellen ...

Und schließlich lautet die erste Zeile der öffentlichen Methode im Code wie folgt:

ValidationUtils.getNullValidator().addParam(plans, "plans").addParam(persons, "persons").validate();

Beachten Sie, dass addParam () self zurückgibt, sodass Sie weitere zu überprüfende Parameter hinzufügen können.

Die Methode validate()wird aktiviert, ValidationExceptionwenn einer der Parameter null ist (aktiviert oder deaktiviert ist eher ein Design- / Geschmacksproblem, aber my ValidationExceptionist aktiviert).

void validate() throws ValidationException;

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.

Oleg
quelle
3
Absolut. Anwendungen, die nur den Fehler und den Absturz auslösen, sind von höherer Qualität, da es keinen Zweifel gibt, wenn sie nicht funktionieren. Anwendungen, die die Fehler bestenfalls verschlucken, werden ordnungsgemäß abgebaut, funktionieren jedoch normalerweise nicht auf schwer erkennbare Weise und werden nicht behoben. Und wenn das Problem bemerkt wird, sind sie viel schwieriger zu debuggen.
Paul Jackson
35

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:

  1. Lassen Sie die Ausnahmen durchlaufen - fangen Sie sie an der Hauptschleife oder in einer anderen Verwaltungsroutine ab.

    • Überprüfen Sie die Fehlerbedingungen und behandeln Sie sie entsprechend

Schauen Sie sich auch die aspektorientierte Programmierung an - sie bietet eine gute Möglichkeit, sie if( o == null ) handleNull()in Ihren Bytecode einzufügen .

xtofl
quelle
35

Zusätzlich zur Verwendung können assertSie Folgendes verwenden:

if (someobject == null) {
    // Handle null here then move on.
}

Das ist etwas besser als:

if (someobject != null) {
    .....
    .....



    .....
}
Fastcodejava
quelle
2
Mh, warum das? Bitte fühlen Sie sich nicht defensiv, ich möchte nur mehr über Java erfahren :)
Matthias Meid
9
@Mudu In der Regel bevorzuge ich, dass der Ausdruck in einer if-Anweisung eine "positivere" Anweisung ist als eine "negative". Wenn ich also sehen if (!something) { x(); } else { y(); }würde, wäre ich geneigt, es so umzugestalten if (something) { y(); } else { x(); }(obwohl man argumentieren könnte, dass dies != nulldie 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.
MatrixFrog
1
Dies ist, was ich auch tue. Hält den Code meiner Meinung nach sauber.
Koray Tugay
34

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 elseKonstrukten!

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.

class C {
    private final MyType mustBeSet;
    public C(MyType mything) {
       mustBeSet=Contract.notNull(mything);
    }
   private String name = "<unknown>";
   public void setName(String s) {
      name = Contract.notNull(s);
   }
}


class Contract {
    public static <T> T notNull(T t) { if (t == null) { throw new ContractException("argument must be non-null"); return t; }
}

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.

iangreen
quelle
warum sollte dies herabgestuft werden?
Nach
Ich bin damit einverstanden, dass dieser Ansatz Probleme im Zusammenhang mit Nullen verhindert, anstatt sie durch Speckling-Code-Nullprüfungen überall zu beheben.
ChrisBlom
7
Das Problem bei diesem Ansatz ist, dass wenn der Name nie festgelegt wird, er den Wert "<unbekannt>" hat, der sich wie ein festgelegter Wert verhält. Angenommen, ich muss überprüfen, ob der Name nie festgelegt wurde (unbekannt). Ich muss einen Zeichenfolgenvergleich mit dem speziellen Wert "<unbekannt>" durchführen.
Steve Kuo
1
Wirklich guter Punkt Steve. Was ich oft mache, ist, diesen Wert als Konstante zu haben, z. B. public static final String UNSET = "__ unset" ... private String field = UNSET ... dann private boolean isSet () {return UNSET.equals (field); }
Ianpojman
IMHO, Dies ist eine Implementierung von Null Object Pattern mit einer Selbstimplementierung von Optional (Contract). Wie verhält es sich in der Persistenzklassenklasse? Ich sehe in diesem Fall keine Anwendbarkeit.
Kurapika
31

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:

Optional<T>ist eine Möglichkeit, eine nullfähige T-Referenz durch einen Wert ungleich Null zu ersetzen. Eine Option kann entweder eine T-Referenz ungleich Null enthalten (in diesem Fall sagen wir, dass die Referenz "vorhanden" ist), oder sie kann nichts enthalten (in diesem Fall sagen wir, dass die Referenz "nicht vorhanden" ist). Es wird nie gesagt, dass es "null enthält".

Verwendungszweck:

Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5
Murat
quelle
@CodyGuldner Richtig, Cody. Ich habe ein relevantes Zitat aus dem Link bereitgestellt, um mehr Kontext zu geben.
Murat Derya Özen
25

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

public Optional<Service> getRefrigertorControl() {
      Service s = new  RefrigeratorService();
       //...
      return Optional.ofNullable(s);
   }

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, entweder Optional.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 ref = homeServices.getRefrigertorControl();
ref.ifPresent(HomeServices::switchItOn);

Optional.ifPresent ruft den angegebenen Consumer mit einer Referenz auf, wenn es sich um einen Wert ungleich Null handelt. Ansonsten macht es nichts.

@FunctionalInterface
public interface Consumer<T>

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 CodebeispielHomeService.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:

public static Optional<HomeServices> get() {
    service = Optional.of(service.orElse(new HomeServices()));
    return service;
}

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:

import java.util.Optional;
public class HomeServices {
    private static final int NOW = 0;
    private static Optional<HomeServices> service;

public static Optional<HomeServices> get() {
    service = Optional.of(service.orElse(new HomeServices()));
    return service;
}

public Optional<Service> getRefrigertorControl() {
    Service s = new  RefrigeratorService();
    //...
    return Optional.ofNullable(s);
}

public static void main(String[] args) {
    /* Get Home Services handle */
    Optional<HomeServices> homeServices = HomeServices.get();
    if(homeServices != null) {
        Optional<Service> refrigertorControl = homeServices.get().getRefrigertorControl();
        refrigertorControl.ifPresent(HomeServices::switchItOn);
    }
}

public static void switchItOn(Service s){
         //...
    }
}

Der komplette Beitrag ist NPE sowie null check-free Code… Wirklich? .

Yogesh Devatraj
quelle
Es gibt eine Null-Prüfung im obigen Code, if(homeServices != null) {die in geändert werden kann homeServices.ifPresent(h -> //action).
KrishPrabakar
23

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.

Herr Palo
quelle
Michael Feathers hat einen kurzen und interessanten Text über Ansätze wie den von Ihnen erwähnten geschrieben: manuelp.newsblur.com/site/424
ivan.aguirre
21

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.

NullPointerExceptionist 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!

OscarRyz
quelle
19

Die wahrscheinlich beste Alternative für Java 8 oder höher ist die Verwendung der OptionalKlasse.

Optional stringToUse = Optional.of("optional is there");
stringToUse.ifPresent(System.out::println);

Dies ist besonders praktisch für lange Ketten möglicher Nullwerte. Beispiel:

Optional<Integer> i = Optional.ofNullable(wsObject.getFoo())
    .map(f -> f.getBar())
    .map(b -> b.getBaz())
    .map(b -> b.getInt());

Beispiel, wie eine Ausnahme auf null ausgelöst wird:

Optional optionalCarNull = Optional.ofNullable(someNull);
optionalCarNull.orElseThrow(IllegalStateException::new);

Java 7 führte die Objects.requireNonNullMethode ein, die nützlich sein kann, wenn etwas auf Nicht-Nullheit überprüft werden soll. Beispiel:

String lowerVal = Objects.requireNonNull(someVar, "input cannot be null or empty").toLowerCase();
Raghu K Nair
quelle
17

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:

if(object == null){
   //you called my method badly!

}}

oder

if(str.length() == 0){
   //you called my method badly again!
}

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:

getCustomerAccounts(@NotEmpty String customerId,@Size(min = 1) String accountType)

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)

public class Car {

   @NotNull
   private String manufacturer;

   @NotNull
   @Size(min = 2, max = 14)
   private String licensePlate;

   @Min(2)
   private int seatCount;

   // ...
}
Alireza Fattahi
quelle
javaxist per Definition nicht "Core Java".
Tomas
17

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.

luke1985
quelle
Die Lösung mit "hasBackground ()" hat einen Nachteil - sie ist nicht threadsicher. Wenn Sie zwei Methoden anstelle einer aufrufen müssen, müssen Sie die gesamte Sequenz in einer Multithread-Umgebung synchronisieren.
pkalinow
@pkalinow Sie haben ein erfundenes Beispiel erstellt, um darauf hinzuweisen, dass diese Lösung einen Nachteil hat. Wenn Code nicht für die Ausführung in Multithread-Anwendungen vorgesehen ist, gibt es keinen Nachteil. Ich könnte Ihnen wahrscheinlich 90% Ihres Codes geben, der nicht threadsicher ist. Wir sprechen hier nicht über diesen Aspekt des Codes, sondern über das Entwurfsmuster. Und Multithreading ist ein Thema für sich.
Luke1985
Natürlich ist dies in einer Single-Thread-Anwendung kein Problem. Ich habe diesen Kommentar gegeben, weil es manchmal ein Problem ist.
pkalinow
@pkalinow Wenn Sie dieses Thema genauer untersuchen, werden Sie feststellen, dass das Null-Objekt-Entwurfsmuster die Multithreading-Probleme nicht behebt. Es ist also irrelevant. Und um ehrlich zu sein, ich habe Orte gefunden, an denen dieses Muster gut passt, also ist meine ursprüngliche Antwort eigentlich ein bisschen falsch.
Luke1985
16
  1. Initialisieren Sie niemals Variablen auf Null.
  2. Wenn (1) nicht möglich ist, initialisieren Sie alle Sammlungen und Arrays, um Sammlungen / Arrays zu leeren.

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.

// Bad
ArrayList<String> lemmings;
String[] names;

void checkLemmings() {
    if (lemmings != null) for(lemming: lemmings) {
        // do something
    }
}



// Good
ArrayList<String> lemmings = new ArrayList<String>();
String[] names = {};

void checkLemmings() {
    for(lemming: lemmings) {
        // do something
    }
}

Das ist ein winziger Aufwand, aber es lohnt sich für saubereren Code und weniger NullPointerExceptions.

Stuart Axon
quelle
3
+1 Dem stimme ich zu. Sie sollten niemals halb initialisierte Objekte zurückgeben. Jaxb-bezogener Code und Bean-Code sind hierfür notiroius. Es ist eine schlechte Praxis. Alle Sammlungen sollten initialisiert werden und alle Objekte sollten (idealerweise) ohne Nullreferenzen existieren. Stellen Sie sich ein Objekt vor, das eine Sammlung enthält. Es ist unvernünftig und dumm zu überprüfen, ob das Objekt nicht null ist, ob die Sammlung nicht null ist und ob die Sammlung keine null Objekte enthält.
ggb667
15

Dies ist der häufigste Fehler, der bei den meisten Entwicklern aufgetreten ist.

Wir haben verschiedene Möglichkeiten, damit umzugehen.

Ansatz 1:

org.apache.commons.lang.Validate //using apache framework

notNull (Objektobjekt, String-Nachricht)

Ansatz 2:

if(someObject!=null){ // simply checking against null
}

Ansatz 3:

@isNull @Nullable  // using annotation based validation

Ansatz 4:

// by writing static method and calling it across whereever we needed to check the validation

static <T> T isNull(someObject e){  
   if(e == null){
      throw new NullPointerException();
   }
   return e;
}
Sireesh Yarlagadda
quelle
Anzeige. 4. Es ist nicht sehr nützlich - wenn Sie überprüfen, ob ein Zeiger null ist, möchten Sie wahrscheinlich eine Methode dafür aufrufen. Wenn Sie eine Methode für null aufrufen, erhalten Sie dasselbe Verhalten - NullPointerException.
pkalinow
11
public static <T> T ifNull(T toCheck, T ifNull) {
    if (toCheck == null) {
           return ifNull;
    }
    return toCheck;
}
tltester
quelle
2
Was ist los mit dieser Methode, ich denke, @tltester möchte nur einen Standardwert angeben, wenn es null ist, was Sinn macht.
Sawyer
1
Es gibt eine solche Methode in Apache commons-lang : ObjectUtils.defaultIfNull(). Es gibt noch eine allgemeinere : ObjectUtils.firstNonNull(), die verwendet werden kann, um eine erniedrigende Strategie umzusetzen:firstNonNull(bestChoice, secondBest, thirdBest, fallBack);
ivant