Ich komme aus einem .NET-Hintergrund und arbeite jetzt in Java.
Gegenwärtig habe ich große Probleme, eine API defensiv gegen fehlerhafte Eingaben zu entwickeln. Sagen wir, ich habe den folgenden Code (nahe genug):
%Vor%Dieser Code kann jedoch aus zwei Gründen fehlschlagen:
null
-Knoten. In .NET würde ich ein ArgumentNullException
(eher als ein NullReferenceException
!) oder ein ArgumentException
bzw. übergibt den Namen des problematischen Arguments ( node
) als string
Argument.
Java scheint keine entsprechenden Ausnahmen zu haben. Ich erkenne, dass ich spezifischer sein könnte und nur die Ausnahme schreibe, die der Situation am nächsten kommt, oder sogar meine eigene Ausnahmeklasse für die spezifische Situation schreibe.
Ist das die beste Praxis? Oder gibt es universelle Klassen, die in .NET mit ArgumentException
vergleichbar sind?
Ist es in diesem Fall sogar sinnvoll, gegen null
zu prüfen? Der Code wird trotzdem fehlschlagen und der Stack-Trace der Ausnahme enthält den obigen Methodenaufruf. Die Überprüfung gegen null
erscheint redundant und übermäßig. Zugegeben, der Stack-Trace wird etwas sauberer sein (da sein Ziel die obige Methode ist, anstatt eine interne Prüfung in der HashMap
-Implementierung der JRE). Dies muss jedoch mit den Kosten einer zusätzlichen if
-Anweisung verrechnet werden, die darüber hinaus nie auftreten sollte - schließlich ist die Weitergabe von null
an die obige Methode keine erwartete Situation, Es ist ein ziemlich dummer Bug. Erwartet, dass es geradezu paranoid ist - und es wird mit der gleichen Ausnahme scheitern, selbst wenn ich nicht danach suche.
[Wie bereits in den Kommentaren erwähnt, erlaubt HashMap.put
tatsächlich null
-Werte für den Schlüssel. Also wäre ein Check gegen null
hier nicht unbedingt überflüssig.]
Verschiedene Gruppen haben unterschiedliche Standards.
Erstens, ich nehme an, Sie kennen den Unterschied zwischen RuntimeException
s (nicht markiert) und normal Exception
s (markiert), wenn nicht, dann sehen Sie diese Frage und die Antworten . Wenn Sie Ihre eigene Ausnahme schreiben, können Sie sie erzwingen, während beide NullPointerException
und IllegalArgumentException
RuntimeExceptions sind, die in einigen Kreisen verpönt sind.
Zweitens, wie bei Ihnen, haben Gruppen, mit denen ich gearbeitet habe, aber nicht aktiv Behauptungen, aber wenn Ihr Team (oder Verbraucher der API) entschieden hat, dass es Behauptungen verwendet, klingt Assert genau wie der richtige Mechanismus.
Wenn ich du wäre, würde ich NullPointerException
verwenden. Der Grund dafür ist Präzedenzfall. Nehmen Sie ein Java-API-Beispiel von Sun, zum Beispiel java.util.TreeSet . Dies verwendet NPEs für genau diese Art von Situation, und während es so aussieht, als ob Ihr Code nur eine Null verwendet, ist es völlig angemessen.
Wie andere gesagt haben, ist IllegalArgumentException
eine Option, aber ich denke, dass NullPointerException kommunikativer ist.
Wenn diese API für externe Firmen / Teams gedacht ist, würde ich bei NullPointerException
bleiben, aber stelle sicher, dass sie im Javadoc deklariert ist. Wenn es für den internen Gebrauch ist, dann könnten Sie entscheiden, dass das Hinzufügen Ihrer eigenen Exception-Hierarchie lohnenswert ist, aber ich persönlich finde, dass APIs, die riesige Ausnahme-Hierarchien hinzufügen, die nur printStackTrace()
d sind oder protokolliert werden, nur eine Verschwendung von Aufwand sind.
Am Ende des Tages ist die Hauptsache, dass Ihr Code klar kommuniziert. Eine lokale Ausnahme-Hierarchie ist wie ein lokaler Jargon - sie fügt Informationen für Insider hinzu, kann aber Außenstehende verblüffen.
Was die Überprüfung gegen null betrifft, würde ich argumentieren, dass es Sinn macht. Erstens können Sie eine Nachricht über das, was Null war (dh Knoten oder Token) hinzufügen, wenn Sie die Ausnahme konstruieren, die hilfreich wäre. Zweitens könnten Sie in Zukunft eine Map
-Implementierung verwenden, die null
zulässt, und dann würden Sie die Fehlerprüfung verlieren. Die Kosten sind fast nichts. Wenn ein Profiler also nicht sagt, dass es ein Problem mit der inneren Schleife ist, würde ich mir keine Sorgen machen.
Die standardmäßige Java-Ausnahme ist IllegalArgumentException
. Einige werden NullPointerException
ausgeben, wenn das Argument null ist, aber für mich hat NPE die Konnotation "jemand vermasselt", und Sie möchten nicht, dass Clients Ihrer API denken, dass Sie nicht wissen, was Sie tun.
Überprüfen Sie bei öffentlichen APIs die Argumente und schlagen Sie früh und sauber fehl. Die Zeit / Kosten spielen kaum eine Rolle.
In Java würden Sie normalerweise eine IllegalArgumentException
auslösenWenn Sie einen Leitfaden zum Schreiben von gutem Java-Code benötigen, kann ich das Buch Effektives Java wärmstens empfehlen > von Joshua Bloch.
Es scheint, dass dies eine angemessene Verwendung für eine Bestätigung :
%Vor%Ihr Ansatz hängt ganz davon ab, welchen Vertrag Ihre Funktion den Anrufern anbietet - ist es eine Voraussetzung, dass der Knoten nicht null ist?
Wenn dies der Fall ist, sollten Sie eine Ausnahme auslösen, wenn der Knoten null ist, da es sich um eine Vertragsverletzung handelt. Wenn dies nicht der Fall ist, sollte Ihre Funktion den Null-Knoten automatisch behandeln und entsprechend antworten.
Ich denke viel hängt vom Vertrag der Methode ab und wie gut der Anrufer bekannt ist.
An einem bestimmten Punkt des Prozesses konnte der Aufrufer Maßnahmen ergreifen, um den Knoten vor dem Aufruf der Methode zu validieren. Wenn Sie den Anrufer kennen und wissen, dass diese Knoten immer validiert sind, denke ich, dass es in Ordnung ist anzunehmen, dass Sie gute Daten erhalten. Im Wesentlichen liegt die Verantwortung beim Anrufer.
Wenn Sie jedoch zum Beispiel eine Bibliothek eines Drittanbieters bereitstellen, die verteilt wird, müssen Sie den Knoten auf Nullen, Etcs ... validieren.
Eine illegalArugementException ist der Java-Standard, ist aber auch eine RunTimeException. Wenn Sie also den Aufrufer zwingen möchten, die Ausnahme zu behandeln, müssen Sie eine Prüfausnahme bereitstellen, wahrscheinlich eine benutzerdefinierte, die Sie erstellen.
Ich persönlich möchte, dass NullPointerExceptions NUR zufällig auftreten, also muss etwas anderes verwendet werden, um anzuzeigen, dass ein ungültiger Argumentwert übergeben wurde. IllegalArgumentException ist dafür geeignet.
%Vor%Dies sollte sowohl für diejenigen, die den Code lesen, als auch für die arme Seele, die um 3 Uhr morgens einen Unterstützungsruf bekommt, ausreichen.
(und, geben Sie IMMER einen erklärenden Text für Ihre Ausnahmen, Sie schätzen sie einen traurigen Tag)
wie der andere: java.lang.IllegalArgumentException. Fragen Sie beim Überprüfen von "null Node", wie Sie fehlerhafte Eingaben bei der Node-Erstellung überprüfen?
Ich muss niemanden zufrieden stellen, also was ich jetzt als kanonischen Code mache, ist
%Vor%was mir viel Schlaf bringt.
Andere werden nicht zustimmen.
Tags und Links java exception defensive-programming