4423 Stimmen

Vermeiden von NullPointerException in Java

Ich benutze object != null eine Menge zu vermeiden NullPointerException .

Was ist eine Alternative zu:

if (someobject != null) {
    someobject.doCalc();
}

144 Stimmen

@Shervin Die Förderung von Nullen macht den Code weniger verständlich und weniger zuverlässig.

85 Stimmen

Die Nichtverwendung von Null ist den meisten anderen Vorschlägen hier überlegen. Werfen Sie Ausnahmen, geben Sie keine Nullen zurück oder erlauben Sie Nullen. BTW - 'assert' Schlüsselwort ist nutzlos, weil es standardmäßig deaktiviert ist. Verwenden Sie einen immer aktivierten Fehler-Mechanismus

0 Stimmen

Sie können eine Klasse erstellen, die auf Nullwerte oder Nullobjekte prüft. Das wird Ihnen helfen, die Wiederverwendbarkeit zu verbessern. stackoverflow.com/a/16833309/1490962

2866voto

cletus Punkte 596503

Das klingt für mich nach einem recht häufigen Problem, mit dem sich Nachwuchs- und fortgeschrittene Entwickler irgendwann konfrontiert sehen: Sie kennen die Verträge, an denen sie beteiligt sind, entweder nicht oder trauen ihnen nicht und überprüfen sie defensiv auf Nullen. Wenn sie ihren eigenen Code schreiben, neigen sie außerdem dazu, sich darauf zu verlassen, dass Nullen zurückgegeben werden, um etwas anzuzeigen, so dass der Aufrufer auf Nullen prüfen muss.

Anders ausgedrückt: Es gibt zwei Fälle, in denen die Nullprüfung zum Tragen kommt:

  1. Wenn null eine gültige Antwort im Sinne des Vertrages ist; und

  2. Wo es keine gültige Antwort ist.

(2) ist einfach. Ab Java 1.7 können Sie verwenden Objects.requireNonNull(foo) . (Wenn Sie an einer früheren Version festhalten, dann assert Ionen kann eine gute Alternative sein.)

Die "richtige" Verwendung dieser Methode sieht folgendermaßen aus. Die Methode gibt das übergebene Objekt zurück und wirft ein NullPointerException wenn das Objekt null ist. Dies bedeutet, dass der zurückgegebene Wert immer ungleich Null ist. Die Methode ist in erster Linie für die Validierung von Parametern gedacht.

public Foo(Bar bar) {
    this.bar = Objects.requireNonNull(bar);
}

Es kann auch wie ein assert ion, da es eine Ausnahme auslöst, wenn das Objekt null ist. Bei beiden Verwendungen kann eine Meldung hinzugefügt werden, die in der Ausnahme angezeigt wird. Im Folgenden wird sie wie eine Assertion verwendet und mit einer Meldung versehen.

Objects.requireNonNull(someobject, "if someobject is null then something is wrong");
someobject.doCalc();

Im Allgemeinen wird eine bestimmte Ausnahme wie NullPointerException wenn ein Wert null ist, es aber nicht sein sollte, ist besser, als eine allgemeinere Ausnahme auszulösen wie AssertionError . Dies ist der Ansatz, den die Java-Bibliothek verfolgt; sie bevorzugt NullPointerException über IllegalArgumentException wenn ein Argument nicht null sein darf.

(1) ist ein bisschen schwieriger. Wenn Sie keine Kontrolle über den Code haben, den Sie aufrufen, sitzen Sie fest. Wenn null eine gültige Antwort ist, müssen Sie dies überprüfen.

Wenn es sich jedoch um Code handelt, den Sie kontrollieren (und das ist oft der Fall), sieht die Sache anders aus. Vermeiden Sie die Verwendung von Nullen als Antwort. Bei Methoden, die Sammlungen zurückgeben, ist es einfach: Sie geben so gut wie immer leere Sammlungen (oder Arrays) anstelle von Nullen zurück.

Bei Nicht-Sammlungen könnte 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);
}

wo der Parser rohe Benutzereingaben entgegennimmt und etwas findet, was zu tun ist, wenn Sie vielleicht eine Befehlszeilenschnittstelle für etwas implementieren. Nun könnte man den Vertrag so gestalten, dass er null zurückgibt, wenn es keine passende Aktion gibt. Das führt zu der Nullprüfung, von der Sie sprechen.

Eine alternative Lösung ist, niemals null zurückzugeben und stattdessen die Null-Objekt-Muster :

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();
}

a

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

was ein viel besseres Design ist, weil es zu einem prägnanteren Code führt.

Abgesehen davon ist es vielleicht durchaus angebracht, dass die findAction()-Methode eine Exception mit einer aussagekräftigen Fehlermeldung auslöst - insbesondere in diesem Fall, in dem Sie sich auf Benutzereingaben verlassen. Es wäre viel besser, wenn die findAction-Methode eine Exception auslösen würde, als wenn die aufrufende Methode mit einer einfachen NullPointerException ohne Erklärung abbricht.

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

Oder wenn Sie den Try/Catch-Mechanismus für zu hässlich halten, sollte Ihre Standardaktion anstelle von Do Nothing eine Rückmeldung an den Benutzer 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);
        }
    }
}

8 Stimmen

Nette Antwort, insbesondere die Erwähnung von Behauptungen. Ich kam von C und benutze sie ständig. Was Null-Objekte betrifft, so sind sie KEINE Wunderwaffe. Ich habe oft Stunden damit verbracht, Code zu debuggen, bei dem sich herausstellte, dass ein Null-Objekt verwendet wurde, das nichts tat (oder seine Standardwerte zurückgab), obwohl eine NPE das Problem viel deutlicher angezeigt hätte. Dann muss man also eine "Null-Objekt-Prüfung" statt einer Null-Prüfung durchführen und hat nichts gewonnen, sondern nur an Klarheit verloren. Heutzutage, wenn ich Null nicht vermeiden kann, dokumentiere ich es einfach deutlich und das war's.

717voto

Luca Molteni Punkte 5081

Wenn Sie eine Java-IDE verwenden (oder dies planen), wie JetBrains IntelliJ IDEA , Eclipse o Netbeans oder einem Tool wie findbugs können Sie dieses Problem mit Anmerkungen lösen.

Im Grunde genommen haben Sie @Nullable y @NotNull .

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

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

oder

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

Das zweite Beispiel lässt sich (in IntelliJ IDEA) nicht kompilieren.

Wenn Sie die erste helloWorld() Funktion in einem anderen Teil des Codes:

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

Nun wird der IntelliJ IDEA Compiler Ihnen sagen, dass die Prüfung nutzlos ist, da die helloWorld() Funktion wird nicht zurückgegeben null nie.

Parameter verwenden

void someMethod(@NotNull someParameter) { }

wenn Sie etwas schreiben wie:

someMethod(null);

Das lässt sich nicht kompilieren.

Letztes Beispiel mit @Nullable

@Nullable iWantToDestroyEverything() { return null; }

Dies zu tun

iWantToDestroyEverything().something();

Und Sie können sicher sein, dass das nicht passieren wird :)

Es ist eine nette Möglichkeit, den Compiler etwas mehr prüfen zu lassen, als er es normalerweise tut, und Ihre Verträge zu erzwingen, um stärker zu sein. Leider wird es nicht von allen Compilern unterstützt.

Ab IntelliJ IDEA 10.5 wurde die Unterstützung für alle anderen @Nullable @NotNull Implementierungen.

Siehe Blogbeitrag Flexiblere und konfigurierbare @Nullable/@NotNull-Anmerkungen .

134 Stimmen

@NotNull , @Nullable und andere Nichtigkeitsvermerke sind Teil von JSR 305 . Sie können sie auch verwenden, um potenzielle Probleme mit Tools wie FindBugs .

37 Stimmen

Ich finde es seltsam ärgerlich, dass die @NotNull & @Nullable Schnittstellen leben im Paket com.sun.istack.internal . (Ich denke, ich verbinde com.sun mit Warnungen über die Verwendung einer proprietären API).

22 Stimmen

Code-Portabilität geht null mit jetbrains.I würde zweimal denken (Quadrat) vor dem Binden auf ide level.Like Jacek S sagte, sie sind Teil der JSR jede Weise, die ich dachte, war JSR303 durch die Art und Weise.

353voto

myplacedk Punkte 1534

Wenn Null-Werte nicht erlaubt sind

Wenn Ihre Methode von außen aufgerufen wird, beginnen Sie mit etwas wie diesem:

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

Im weiteren Verlauf der Methode werden Sie dann wissen, dass object ist nicht null.

Wenn es sich um eine interne Methode handelt (nicht Teil einer API), dokumentieren Sie einfach, dass sie nicht null sein kann, und das war's.

Ejemplo:

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

Wenn Ihre Methode jedoch nur den Wert weitergibt, und die nächste Methode ihn weitergibt usw., könnte es problematisch werden. In diesem Fall sollten Sie das Argument wie oben beschrieben überprüfen.

Wenn Null erlaubt ist

Das kommt ganz darauf an. Wenn ich finde, dass ich oft etwas wie dies tun:

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

Also verzweige ich und mache zwei völlig unterschiedliche Dinge. Es gibt keinen hässlichen Codeschnipsel, denn ich muss wirklich zwei verschiedene Dinge tun, je nach den Daten. Soll ich zum Beispiel die Eingabe bearbeiten oder einen guten Standardwert berechnen?


Ich verwende eigentlich selten die Redewendung " if (object != null && ... ".

Es ist vielleicht einfacher, Ihnen Beispiele zu geben, wenn Sie zeigen, wo Sie die Redewendung normalerweise verwenden.

103 Stimmen

Welchen Sinn hat es, eine IllegalArgumentException auszulösen? Ich denke, NullPointerException wäre klarer, und das würde auch ausgelöst werden, wenn Sie nicht die Null-Prüfung selbst tun. Ich würde entweder assert oder gar nichts verwenden.

25 Stimmen

Es ist unwahrscheinlich, dass jeder andere Wert als Null akzeptabel ist. Sie könnten IllegalArgumentException, OutOfRageException usw. usw. haben. Manchmal macht das Sinn. In anderen Fällen erstellt man eine Menge von Ausnahmeklassen, die keinen Mehrwert bringen, und verwendet dann einfach IllegalArgumentException. Es macht keinen Sinn, eine Ausnahme für Null-Eingabe und eine andere für alles andere zu haben.

7 Stimmen

Ja, ich stimme dem Fail-Fast-Prinzip zu, aber in dem oben genannten Beispiel wird der Wert nicht weitergegeben, sondern ist das Objekt, auf dem eine Methode aufgerufen werden soll. Es schlägt also gleich schnell fehl, und das Hinzufügen einer Null-Prüfung, nur um eine Ausnahme zu erzeugen, die ohnehin zur gleichen Zeit und am gleichen Ort ausgelöst würde, scheint die Fehlersuche nicht zu erleichtern.

259voto

erickson Punkte 256579

Wow, ich hasse es fast, eine weitere Antwort hinzuzufügen, wenn wir 57 verschiedene Möglichkeiten haben, die NullObject pattern aber ich denke, dass einige Leute, die sich für diese Frage interessieren, gerne wissen möchten, dass es einen Vorschlag für Java 7 gibt, um "nullsichere Handhabung" -eine vereinfachte Syntax für die if-not-equal-null-Logik.

Das von Alex Miller angeführte Beispiel sieht wie folgt aus:

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

El ?. bedeutet, dass der linke Bezeichner nur de-referenziert wird, wenn er nicht null ist, andernfalls wird der Rest des Ausdrucks als null . Einige Leute, wie das Java-Posse-Mitglied Dick Wall und die Wähler bei Devoxx Dieser Vorschlag ist wirklich gut, aber es gibt auch Gegner, die meinen, dass er zu einer stärkeren Nutzung von null als Sentinel-Wert.


Aktualisierung: Eine offizieller Vorschlag für einen null-sicheren Operator in Java 7 wurde unter Projekt Münze. Die Syntax ist ein wenig anders als im obigen Beispiel, aber das Konzept ist dasselbe.


Aktualisierung: Der Vorschlag eines nullsicheren Betreibers wurde nicht in das Projekt Coin aufgenommen. Sie werden diese Syntax also in Java 7 nicht mehr sehen.

23 Stimmen

Ich denke, das ist falsch. Es sollte eine Möglichkeit geben, festzulegen, dass eine bestimmte Variable IMMER ungleich Null ist.

7 Stimmen

Update: Der Vorschlag wird nicht in Java7 aufgenommen. Siehe blogs.sun.com/darcy/entry/project_coin_final_five .

2 Stimmen

Auf derselben Seite finden Sie jedoch auch einen Link zu types.cs.washington.edu/jsr308 für Informationen über die Verwendung des Checker-Frameworks zum Hinzufügen der @Nullable- und @NonNull-Typ-Annotationen in Java 7.

214voto

echox Punkte 9316

Nur für diese Situation -

Keine Überprüfung, ob eine Variable null ist, bevor eine "equals"-Methode aufgerufen wird (Beispiel eines String-Vergleichs unten):

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

führt zu einer NullPointerException si foo gibt es nicht.

Das können Sie vermeiden, wenn Sie Ihre String s so:

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

44 Stimmen

Ich stimme zu - nur in dieser Situation. Ich kann Programmierer nicht ausstehen, die dies auf die nächste unnötige Ebene gebracht haben und if (null != myVar) schreiben... sieht für mich einfach hässlich aus und dient keinem Zweck!

22 Stimmen

Dies ist ein spezielles Beispiel, wahrscheinlich das meistgenutzte, für eine allgemeine gute Praxis: Wenn du es weißt, tu es immer <object that you know that is not null>.equals(<object that might be null>); . Es funktioniert auch bei anderen Methoden als equals wenn Sie den Vertrag kennen und diese Methoden mit null Parameter.

9 Stimmen

Dies ist das erste Beispiel, das ich gesehen habe für Yoda Bedingungen das macht tatsächlich Sinn

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X