Ich habe eine einfache Setter-Methode für eine Eigenschaft und null
ist für diese spezielle Immobilie nicht geeignet. Ich war in dieser Situation immer hin- und hergerissen: Sollte ich eine IllegalArgumentException
oder eine NullPointerException
? Nach den Javadocs scheinen beide geeignet zu sein. Gibt es so etwas wie einen anerkannten Standard? Oder ist das einfach so, dass man das tun sollte, was man bevorzugt, und beides ist wirklich richtig?
Antworten
Zu viele Anzeigen?Sie sollten Folgendes verwenden IllegalArgumentException
(IAE), nicht NullPointerException
(NPE) aus den folgenden Gründen:
Erstens, die NPE JavaDoc listet ausdrücklich die Fälle auf, in denen NPE angemessen ist. Beachten Sie, dass alle diese Fälle ausgelöst werden durch die Laufzeit wenn null
in unangemessener Weise verwendet wird. Im Gegensatz dazu ist die IAE JavaDoc könnte nicht klarer sein: "Wird ausgelöst, um anzuzeigen, dass einer Methode ein illegales oder unangemessenes Argument übergeben wurde." Ja, das sind Sie!
Zweitens, wenn Sie eine NPE in einem Stack-Trace sehen, was nehmen Sie an? Wahrscheinlich, dass jemand eine dereferenzierte null
. Wenn Sie IAE sehen, gehen Sie davon aus, dass der Aufrufer der Methode am oberen Ende des Stacks einen illegalen Wert übergeben hat. Auch hier ist die letztere Annahme richtig, die erste ist irreführend.
Drittens: Da IAE eindeutig für die Validierung von Parametern konzipiert ist, müssen Sie davon ausgehen, dass es die Standardausnahme ist. Warum also sollten Sie stattdessen NPE wählen? Sicherlich nicht, um ein anderes Verhalten zu erreichen - erwarten Sie wirklich, dass der aufrufende Code NPEs getrennt von IAE abfängt und infolgedessen etwas anderes tut? Versuchen Sie, eine spezifischere Fehlermeldung zu übermitteln? Aber das können Sie ohnehin im Text der Ausnahmemeldung tun, wie Sie es auch für alle anderen fehlerhaften Parameter tun sollten.
Viertens werden alle anderen falschen Parameterdaten IAE sein, warum also nicht konsistent sein? Warum ist eine illegale null
so speziell ist, dass es eine gesonderte Ausnahme von allen anderen Arten illegaler Argumente verdient?
Schließlich akzeptiere ich das in anderen Antworten angeführte Argument, dass Teile der Java-API NPE auf diese Weise verwenden. Allerdings ist die Java-API von Ausnahmetypen bis hin zu Namenskonventionen inkonsistent, so dass ich denke, dass das blinde Kopieren (Ihres Lieblingsteils der) Java-API kein ausreichendes Argument ist, um diese anderen Überlegungen zu übertrumpfen.
Der Standard ist der Wurf der NullPointerException
. Das im Allgemeinen unfehlbare "Effective Java" erörtert dies kurz in Punkt 42 (erste Auflage), Punkt 60 (zweite Auflage) oder Punkt 72 (dritte Auflage) "Favor the use of standard exceptions":
"Wohl alle fehlerhaften Methodenaufrufe Methodenaufrufe auf ein illegales Argument oder einen illegalen Zustand, aber andere Ausnahmen werden standardmäßig verwendet für bestimmte Arten von illegalen Argumenten und Zustände. Wenn ein Aufrufer null in einen Parameter, für den Nullwerte verboten sind, schreibt die Konvention vor dass die NullPointerException ausgelöst wird und nicht IllegalArgumentException geworfen wird."
Ich war sehr dafür, die IllegalArgumentException
für Null-Parameter, bis ich heute bemerkte, dass die java.util.Objects.requireNonNull
Methode in Java 7. Mit dieser Methode, anstatt zu tun:
if (param == null) {
throw new IllegalArgumentException("param cannot be null.");
}
können Sie tun:
Objects.requireNonNull(param);
und es wird eine NullPointerException
wenn der Parameter, den Sie ihm übergeben, null
.
Angesichts der Tatsache, dass diese Methode genau in der Mitte der java.util
Ich betrachte seine Existenz als ein ziemlich starkes Indiz dafür, dass das Werfen von NullPointerException
ist "die Java-Art, Dinge zu tun".
Ich glaube, ich bin auf jeden Fall entschlossen.
Beachten Sie, dass die Argumente über hartes Debugging falsch sind, da Sie natürlich eine Nachricht an NullPointerException
zu sagen, was nichtig war und warum es nicht nichtig sein sollte. Genau wie bei IllegalArgumentException
.
Ein zusätzlicher Vorteil von NullPointerException
ist, dass Sie in sehr leistungsintensivem Code auf eine explizite Prüfung auf Null verzichten können (und eine NullPointerException
mit einer freundlichen Fehlermeldung), und verlassen Sie sich einfach auf die NullPointerException
erhalten Sie automatisch, wenn Sie eine Methode mit einem Null-Parameter aufrufen. Wenn Sie eine Methode schnell aufrufen (d.h. schnell scheitern), dann haben Sie im Wesentlichen den gleichen Effekt, nur nicht ganz so benutzerfreundlich für den Entwickler. In den meisten Fällen ist es wahrscheinlich besser, explizit zu prüfen und mit einer nützlichen Nachricht zu werfen, um anzuzeigen, welcher Parameter null war, aber es ist schön, die Möglichkeit zu haben, das zu ändern, wenn die Leistung es erfordert, ohne den veröffentlichten Vertrag der Methode/des Konstruktors zu brechen.
Ich neige dazu, mich am Design der JDK-Bibliotheken zu orientieren, insbesondere an Collections und Concurrency (Joshua Bloch, Doug Lea, diese Jungs wissen, wie man solide APIs entwickelt). Wie auch immer, viele APIs im JDK werfen pro-aktiv NullPointerException
.
Zum Beispiel ist die Javadoc für Map.containsKey
Staaten:
@Wirft NullPointerException, wenn der Schlüssel null ist und diese Karte keine Null-Schlüssel zulässt (optional).
Es ist völlig in Ordnung, seine eigene NPE zu werfen. Die Konvention ist, den Parameternamen, der null war, in die Meldung der Ausnahme aufzunehmen.
Das Muster geht:
public void someMethod(Object mustNotBeNull) {
if (mustNotBeNull == null) {
throw new NullPointerException("mustNotBeNull must not be null");
}
}
Was auch immer Sie tun, lassen Sie nicht zu, dass ein schlechter Wert gesetzt wird und später eine Ausnahme auslöst, wenn ein anderer Code versucht, ihn zu verwenden. Das macht die Fehlersuche zu einem Albtraum. Sie sollten immer dem "Fail-Fast"-Prinzip folgen.
- See previous answers
- Weitere Antworten anzeigen