Sollte eine Abrufmethode 'null' zurückgeben oder eine Ausnahme auslösen, wenn sie den Rückgabewert nicht erzeugen kann? [geschlossen]


503

Ich habe eine Methode, die ein Objekt zurückgeben soll, wenn es gefunden wird.

Wenn es nicht gefunden wird, sollte ich:

  1. return null
  2. eine Ausnahme auslösen
  3. andere

57
Was auch immer Sie tun, stellen Sie sicher, dass Sie es dokumentieren. Ich denke, dieser Punkt ist wichtiger als genau, welcher Ansatz "am besten" ist.
Rik

6
Dies hängt von den vorherrschenden Redewendungen der Programmiersprache ab. Bitte kennzeichnen Sie diese Frage mit einem Programmiersprachen-Tag.
Teddy

3
Die Rückgabe von null kann nur Erfolg oder Misserfolg bedeuten, was sehr oft nicht viele Informationen enthält (einige Methoden können in vielerlei Hinsicht fehlschlagen). Bibliotheken sollten besser Ausnahmen auslösen, um Fehler explizit zu machen. Auf diese Weise kann das Hauptprogramm entscheiden, wie der Fehler auf einer höheren Ebene behandelt werden soll (im Gegensatz zur integrierten Fehlerbehandlungslogik).
3k

1
Mir scheint, die eigentliche Frage ist, ob wir es als außergewöhnlich betrachten sollten, wenn ein Unternehmen nicht gefunden wird, und wenn ja, warum? Niemand hat wirklich ausreichend geantwortet, wie man zu diesem Schluss kommt, und jetzt ist das Q & A geschlossen. Schade, dass sich die Branche in diesem wichtigen Thema nicht einig ist. Ja, ich weiß, es kommt darauf an . Erklären Sie also, warum es mit mehr als "wenn außergewöhnlich, werfen" abhängt
zerquetschen Sie den

Antworten:


484

Wenn Sie immer erwarten, einen Wert zu finden, lösen Sie die Ausnahme aus, wenn sie fehlt. Die Ausnahme würde bedeuten, dass es ein Problem gab.

Wenn der Wert fehlen oder vorhanden sein kann und beide für die Anwendungslogik gültig sind, geben Sie eine Null zurück.

Wichtiger: Was machen Sie an anderen Stellen im Code? Konsistenz ist wichtig.


30
@ Ken: +1, es wäre schön zu erwähnen, dass, wenn Sie eine Ausnahme auslösen, diese aber a priori erkennen können (wie HasItem (...)), der Benutzer die Has * - oder Contains-Methode angeben sollte.
user7116

4
Anstatt einen Wert oder null zurückzugeben, wenn der Wert fehlt, sollten Sie ein Vielleicht <T> zurückgeben. Siehe mikehadlow.blogspot.nl/2011/01/monads-in-c-5-maybe.html .
Erwin Rooijakkers

2
In einer @ErwinRooijakkers Designauswahl können Sie ab Java 8 auch ein optionales <T>
José Andias

2
Ich finde es ein bisschen störend, dass jede Antwort das gleiche Sprichwort wiedergibt: "Wenn es außergewöhnlich ist, werfen Sie." Die meisten Ingenieure werden mit diesem Prinzip vertraut sein. Meiner Meinung nach ist hier die eigentliche Frage ist , wie zu bestimmen , ob es sein sollte außergewöhnlich angesehen. Das OP sucht nach Best Practices in Bezug auf beispielsweise ein Repository-Muster. Wird es normalerweise als außergewöhnlich angesehen, wenn ein Objekt bei einem Primärschlüssel nicht existiert? Ja, das wird seine Domäne bestimmen, aber was schlagen die meisten Experten mit langjähriger Erfahrung vor? Das ist die Art von Antwort, die wir sehen sollten.
Crush

4
@crush Ich denke, ein Leitprinzip ist, welche Parameter an die Funktion übergeben werden . Wenn Sie eine Identität übergeben , wie Sie einen Primärschlüssel erwähnen, sollte dies als außergewöhnlich angesehen werden, wenn dieses Element nicht gefunden wird, da es auf einen inkonsistenten Status im System hinweist. Beispiel: GetPersonById(25)würde werfen, wenn diese Person gelöscht wurde, GetPeopleByHairColor("red")würde aber ein leeres Ergebnis zurückgeben. Ich denke, die Parameter sagen etwas über die Erwartungen aus.
John Knoop

98

Eine Ausnahme nur auslösen, wenn es sich wirklich um einen Fehler handelt. Wenn erwartet wird, dass das Verhalten des Objekts nicht vorhanden ist, geben Sie die Null zurück.

Ansonsten ist es eine Frage der Präferenz.


4
Ich stimme nicht zu Sie können Ausnahmen als Statuscodes auslösen: "NotFoundException"
ACV

Es sollte sicherlich keine Frage der Präferenz sein. Auf diese Weise erhalten wir inkonsistenten Code - wenn nicht im Code Ihres Teams, dann mit ziemlicher Sicherheit, wenn Sie anderen Entwicklercode mit Ihrem eigenen (externen Bibliotheken) verflechten.
Crush

4
Ich denke, die Behandlung des Nullfalls ist viel einfacher als "NotFoundException". Überlegen Sie, wie viele Zeilen Try-Catch Sie um jede einzelne Wiederholungsanforderung schreiben müssen, die eine "NotFoundException" auslöst ... Es ist schmerzhaft, den gesamten Code in meinen Augen fertig zu stellen.
Visc

Ich möchte Tony Hoare zitieren: "Ich nenne es meinen Milliarden-Dollar-Fehler." Ich würde nicht null zurückgeben, ich würde entweder eine Ausnahme auslösen und sie korrekt behandeln oder ein leeres Objekt zurückgeben.
sieben

70

Wenn die Methode immer ein Objekt zurückgeben soll, gehen Sie in der Regel mit der Ausnahme vor. Wenn Sie die gelegentliche Null antizipieren und auf bestimmte Weise damit umgehen möchten, wählen Sie die Null.

Was auch immer Sie tun, ich rate dringend von der dritten Option ab: Rückgabe einer Zeichenfolge mit der Aufschrift "WTF".


Plus eins, weil ich das in den guten alten Zeiten mehr als ein paar Mal als schnelle schmutzige "zeitliche" Lösung getan habe ... keine gute Idee. Insbesondere, wenn es überprüft wird, wenn Sie ein Student sind.
Rciafardone

14
Ich war nach unten Abstimmung gehen , da die WTF Optionen genial schien mir ... aber anscheinend habe ich ein Herz
swestner

5
werfen neue WtfExcepti😲n
Kamafeather

Ich denke, es wäre hilfreich, wenn diese Antwort über Gründe sprechen würde, warum eine Methode immer ein Objekt gegenüber "einer gelegentlichen Null" zurückgibt. Was rechtfertigt diese Art von Situation? Geben Sie ein Beispiel dafür, wann ein solcher Umstand vorliegen könnte.
Crush

51

Wenn null niemals einen Fehler anzeigt, geben Sie einfach null zurück.

Wenn null immer ein Fehler ist, wird eine Ausnahme ausgelöst.

Wenn null manchmal eine Ausnahme ist, codieren Sie zwei Routinen. Eine Routine löst eine Ausnahme aus und die andere ist eine boolesche Testroutine, die das Objekt in einem Ausgabeparameter zurückgibt, und die Routine gibt eine falsche zurück, wenn das Objekt nicht gefunden wurde.

Es ist schwer, eine Try-Routine zu missbrauchen. Es ist wirklich leicht zu vergessen, nach Null zu suchen.

Wenn also null ein Fehler ist, schreiben Sie einfach

object o = FindObject();

Wenn die Null kein Fehler ist, können Sie so etwas wie codieren

if (TryFindObject(out object o)
  // Do something with o
else
  // o was not found

1
Dies wäre ein nützlicherer Vorschlag, wenn C # echte Tupel bereitstellen würde, sodass wir die Verwendung eines [out] -Parameters vermeiden könnten. Dies ist jedoch das bevorzugte Muster, also +1.
Erik Forbes

2
Meiner Meinung nach ist der Try-Ansatz der beste. Sie müssen dann nicht nachschlagen, was passiert, wenn das Objekt nicht zurückgegeben werden kann. Mit einer Try-Methode wissen Sie sofort, was zu tun ist.
OregonGhost

erinnert mich an das findund findOrFailvon Laravel Eloquent
vivoconunxino

@ErikForbes Ich weiß, dass Ihr Kommentar alt ist, aber wäre die Antwort nicht gewesen, ein Objekt mit mehreren Eigenschaften zu definieren, das von der TryFindObjectMethode zurückgegeben wird? Tupel scheinen eher ein faules Paradigma für Programmierer zu sein, die sich nicht die Zeit nehmen möchten, ein Objekt zu definieren, das mehrere Werte enthält. Das heißt, im Wesentlichen sind sowieso alle Tupel im Kern.
Crush

@crush - Named Tuple Literals sind eine Option, IMO. Dies ist ein Link zu einem asynchronen Try Get-Muster mit Tupeln. stackoverflow.com/questions/1626597/…
ttugates

26

Ich wollte nur die zuvor genannten Optionen zusammenfassen und einige neue hinzufügen:

  1. return null
  2. eine Ausnahme werfen
  3. Verwenden Sie das Nullobjektmuster
  4. Geben Sie Ihrer Methode einen booleschen Parameter an, damit der Aufrufer auswählen kann, ob Sie eine Ausnahme auslösen sollen
  5. Geben Sie einen zusätzlichen Parameter an, damit der Aufrufer einen Wert festlegen kann, den er zurückerhält, wenn kein Wert gefunden wird

Oder Sie kombinieren diese Optionen:

Stellen Sie mehrere überladene Versionen Ihres Getters bereit, damit der Anrufer entscheiden kann, welchen Weg er einschlagen möchte. In den meisten Fällen hat nur der erste eine Implementierung des Suchalgorithmus, und die anderen umschließen nur den ersten:

Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);

Selbst wenn Sie nur eine Implementierung bereitstellen, möchten Sie möglicherweise eine solche Namenskonvention verwenden, um Ihren Vertrag zu verdeutlichen. Dies hilft Ihnen, falls Sie sich jemals dazu entschließen sollten, auch andere Implementierungen hinzuzufügen.

Sie sollten es nicht überbeanspruchen, aber es kann hilfreich sein, insbesondere beim Schreiben einer Hilfsklasse, die Sie in Hunderten verschiedener Anwendungen mit vielen verschiedenen Konventionen zur Fehlerbehandlung verwenden.


Ich mag die eindeutigen Funktionsnamen, insbesondere orCreate und orDefault.
Marcovtwout

5
Die meisten dieser kann mehr sauber mit geschrieben werden , Expected<T> findObject(String)wo Expected<T>die Funktionen hat orNull(), orThrow(), orSupplied(Supplier<T> supplier), orDefault(T default). Dies abstrahiert das
Abrufen

Ich wusste bis jetzt nichts über Expected <T>. Ich scheine ziemlich neu zu sein und habe möglicherweise nicht existiert, als ich die ursprüngliche Antwort schrieb. Vielleicht sollten Sie Ihren Kommentar zu einer richtigen Antwort machen.
Lena Schimmel

Außerdem ist Expected <T> eine C ++ - Vorlage. Gibt es Implementierungen auch in anderen objektorientierten Sprachen?
Lena Schimmel

In Java 8 ist die Rückgabe von optionalem <T> (in anderen Sprachen möglicherweise <T> usw. genannt) ebenfalls eine Option. Dies zeigt dem Anrufer deutlich an, dass die Rückgabe von nichts eine Möglichkeit ist und nicht kompiliert wird, wenn der Anrufer diese Möglichkeit nicht behandelt hat, im Gegensatz zu null, das (in Java sowieso) kompiliert wird, selbst wenn der Anrufer es nicht überprüft .
Einige Guy

18

Verwenden Sie das Nullobjektmuster oder lösen Sie eine Ausnahme aus.


Das ist die wahre Antwort. Die Rückgabe von null ist eine schreckliche Angewohnheit fauler Programmierer.
Jeremyjjbrown

Ich kann nicht glauben, dass diese Antwort noch nicht an die Spitze gewählt wurde. Dies ist die eigentliche Antwort, und jeder Ansatz ist kinderleicht und spart viel Code-Bloat oder NPEs.
Bane


3
Wenn man das Nullobjektmuster verwendet, wie würde man den Fall, in dem der Schlüssel dem Nullobjekt zugeordnet ist, von dem Fall unterscheiden, in dem der Schlüssel keine Zuordnung hat? Ich würde denken, dass die Rückgabe eines bedeutungslosen Objekts weitaus schlimmer wäre als die Rückgabe von null. Wenn Sie null an Code zurückgeben, der nicht darauf vorbereitet ist, wird im Allgemeinen eine Ausnahme ausgelöst. Nicht die optimale Wahl der Ausnahme, aber dennoch eine Ausnahme. Die Rückgabe eines bedeutungslosen Objekts führt mit größerer Wahrscheinlichkeit dazu, dass der Code fehlerlose Daten fälschlicherweise als korrekt betrachtet.
Supercat

3
Wie würde sich das Nullobjekt für eine Entitätssuche verhalten? Angenommen, Person somePerson = personRepository.find("does-not-exist");diese Methode gibt ein Nullobjekt für die ID zurück does-not-exist. Wofür wäre dann das richtige Verhalten somePerson.getAge()? Derzeit bin ich noch nicht davon überzeugt, dass das Nullobjektmuster die richtige Lösung für die Suche nach Entitäten ist.
Abdull

13

Seien Sie konsistent mit den APIs, die Sie verwenden.


13

Vorteile einer Ausnahme:

  1. Saubererer Kontrollfluss in Ihrem Anrufcode. Wenn Sie auf Null prüfen, wird ein bedingter Zweig eingefügt, der nativ von try / catch verarbeitet wird. Wenn Sie nach null suchen, wird nicht angezeigt, wonach Sie suchen. Suchen Sie nach null, weil Sie nach einem erwarteten Fehler suchen, oder suchen Sie nach null, damit Sie ihn nicht weiter an die Downchain weitergeben ?
  2. Entfernt die Mehrdeutigkeit dessen, was "null" bedeutet. Ist null repräsentativ für einen Fehler oder ist null das, was tatsächlich im Wert gespeichert ist? Schwer zu sagen, wenn Sie nur eine Sache haben, auf die Sie diese Entschlossenheit stützen können.
  3. Verbesserte Konsistenz zwischen dem Methodenverhalten in einer Anwendung. Ausnahmen werden normalerweise in Methodensignaturen angezeigt, sodass Sie besser verstehen können, für welche Randfälle die Methoden in einer Anwendung verantwortlich sind und auf welche Informationen Ihre Anwendung auf vorhersehbare Weise reagieren kann.

Weitere Erläuterungen mit Beispielen finden Sie unter: http://metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/


2
+1, weil Punkt 2 ausgezeichnet ist - null hat nicht die gleiche Bedeutung wie nicht gefunden. Diese werden wichtiger , wenn sie mit dynamischen Sprachen zu tun , wo Null tatsächlich das Objekt sein könnte , wird durch die Funktion gespeichert / abgerufen - und in diesem Fall
Adam Terrey

1
+1 für Punkt 2. Ist null ein Fehler? Ist null, was für den angegebenen Schlüssel gespeichert ist? Zeigt null an, dass der Schlüssel nicht vorhanden ist? Dies sind die eigentlichen Fragen, die deutlich machen, dass die Rückgabe von Null fast nie richtig ist. Dies ist wahrscheinlich die beste Antwort hier, da alle anderen gerade das zweideutige "Wenn es außergewöhnlich ist, werfen"
Crush

12

Es hängt davon ab, ob Ihre Sprache und Ihr Code für Folgendes werben: LBYL (schauen Sie, bevor Sie springen) oder EAFP (leichter um Vergebung zu bitten als um Erlaubnis)

LBYL sagt, Sie sollten nach Werten suchen (also eine Null zurückgeben)
EAFP sagt, Sie sollen einfach die Operation versuchen und sehen, ob sie fehlschlägt (eine Ausnahme ).

obwohl ich oben einverstanden bin .. Ausnahmen sollten für Ausnahme- / Fehlerbedingungen verwendet werden, und die Rückgabe einer Null ist am besten, wenn Prüfungen verwendet werden.


EAFP vs. LBYL in Python:
http://mail.python.org/pipermail/python-list/2003-May/205182.html ( Webarchiv )


3
In einigen Fällen ist EAFP der einzig sinnvolle Ansatz. In einer gleichzeitigen Karte / einem gleichzeitigen Wörterbuch kann beispielsweise nicht gefragt werden, ob eine Zuordnung vorhanden ist, wenn sie angefordert wird.
Supercat

11

Fragen Sie sich einfach: "Ist es ein Ausnahmefall, dass das Objekt nicht gefunden wird?" Wenn dies im normalen Verlauf Ihres Programms erwartet wird, sollten Sie wahrscheinlich keine Ausnahme auslösen (da es sich nicht um ein außergewöhnliches Verhalten handelt).

Kurzversion: Verwenden Sie Ausnahmen, um außergewöhnliches Verhalten zu behandeln, nicht um den normalen Kontrollfluss in Ihrem Programm zu behandeln.

-Alan.


5

Ausnahmen beziehen sich auf Design by Contract.

Die Schnittstelle eines Objekts ist eigentlich ein Vertrag zwischen zwei Objekten, der Anrufer muss den Vertrag erfüllen, sonst kann der Empfänger nur mit einer Ausnahme ausfallen. Es gibt zwei mögliche Verträge

1) Alle Eingaben der Methode sind gültig. In diesem Fall müssen Sie null zurückgeben, wenn das Objekt nicht gefunden wird.

2) nur eine Eingabe ist gültig, dh die, die zu einem gefundenen Objekt führt. In diesem Fall MÜSSEN Sie eine zweite Methode anbieten, mit der der Anrufer feststellen kann, ob die Eingabe korrekt ist. Zum Beispiel

is_present(key)
find(key) throws Exception

WENN und NUR WENN Sie beide Methoden des 2. Vertrages angeben, dürfen Sie eine Ausnahme auslösen, wenn nichts gefunden wird!


4

Ich ziehe es vor, nur eine Null zurückzugeben und mich darauf zu verlassen, dass der Anrufer angemessen damit umgeht. Die (mangels eines besseren Wortes) Ausnahme ist, wenn ich absolut "sicher" bin, dass diese Methode ein Objekt zurückgibt. In diesem Fall ist ein Fehler ein außergewöhnliches sollte und sollte werfen.


4

Kommt darauf an, was es bedeutet, dass das Objekt nicht gefunden wird.

Wenn es sich um einen normalen Zustand handelt, geben Sie null zurück. Dies ist nur etwas, das gelegentlich passieren kann, und die Anrufer sollten es überprüfen.

Wenn es sich um einen Fehler handelt, lösen Sie eine Ausnahme aus. Die Aufrufer sollten entscheiden, was mit der Fehlerbedingung eines fehlenden Objekts geschehen soll.

Letztendlich würde beides funktionieren, obwohl die meisten Leute es im Allgemeinen für eine gute Praxis halten, Ausnahmen nur dann zu verwenden, wenn etwas Außergewöhnliches passiert ist.


2
Wie würden Sie die Aussage " Normaler Zustand " erläutern und nach welchen Kriterien werden Sie sie mit einem Fehler unterscheiden?
user1451111

4

Hier noch ein paar Vorschläge.

Wenn Sie eine Sammlung zurückgeben, vermeiden Sie die Rückgabe von null. Geben Sie eine leere Sammlung zurück, wodurch die Aufzählung ohne vorherige Nullprüfung einfacher zu handhaben ist.

Mehrere .NET-APIs verwenden das Muster eines throwOnError-Parameters, der dem Aufrufer die Wahl lässt, ob es sich wirklich um eine Ausnahmesituation handelt oder nicht, wenn das Objekt nicht gefunden wird. Type.GetType ist ein Beispiel dafür. Ein weiteres häufiges Muster bei BCL ist das TryGet-Muster, bei dem ein Boolescher Wert zurückgegeben und der Wert über einen Ausgabeparameter übergeben wird.

Unter bestimmten Umständen können Sie auch das Nullobjektmuster berücksichtigen, das entweder eine Standardversion oder eine Version ohne Verhalten sein kann. Der Schlüssel ist, Nullprüfungen in der gesamten Codebasis zu vermeiden. Weitere Informationen finden Sie hier http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx


3

In einigen Funktionen füge ich einen Parameter hinzu:

..., bool verify = true)

True bedeutet werfen, false bedeutet, einen Fehlerrückgabewert zurückzugeben. Auf diese Weise hat jeder, der diese Funktion verwendet, beide Optionen. Der Standardwert sollte true sein, zum Nutzen derer, die die Fehlerbehandlung vergessen.


3

Geben Sie eine Null zurück, anstatt eine Ausnahme auszulösen, und dokumentieren Sie die Möglichkeit eines Null-Rückgabewerts in der API-Dokumentation. Wenn der aufrufende Code die API nicht berücksichtigt und nach dem Nullfall sucht, führt dies höchstwahrscheinlich ohnehin zu einer Art "Nullzeigerausnahme" :)

In C ++ kann ich mir drei verschiedene Varianten des Einrichtens einer Methode vorstellen, die ein Objekt findet.

Option A.

Object *findObject(Key &key);

Gibt null zurück, wenn ein Objekt nicht gefunden werden kann. Schön und einfach. Ich würde mit diesem gehen. Die folgenden alternativen Ansätze richten sich an Personen, die Out-Params nicht hassen.

Option B.

void findObject(Key &key, Object &found);

Übergeben Sie einen Verweis auf eine Variable, die das Objekt empfangen soll. Die Methode hat eine Ausnahme ausgelöst, wenn ein Objekt nicht gefunden werden kann. Diese Konvention ist wahrscheinlich besser geeignet, wenn nicht wirklich erwartet wird, dass ein Objekt nicht gefunden wird. Daher wird eine Ausnahme ausgelöst, um anzuzeigen, dass es sich um einen unerwarteten Fall handelt.

Option C.

bool findObject(Key &key, Object &found);

Die Methode gibt false zurück, wenn ein Objekt nicht gefunden werden kann. Der Vorteil gegenüber Option A besteht darin, dass Sie in einem klaren Schritt nach dem Fehlerfall suchen können:

if (!findObject(myKey, myObj)) { ...

3

Ich beziehe mich nur auf den Fall, in dem null nicht als außergewöhnliches Verhalten angesehen wird. Ich bin definitiv für die try-Methode. Es ist klar, dass Sie nicht "das Buch lesen" oder "schauen müssen, bevor Sie springen", wie hier gesagt wurde

also im Grunde genommen:

bool TryFindObject(RequestParam request, out ResponseParam response)

und dies bedeutet, dass der Code des Benutzers ebenfalls klar ist

...
if(TryFindObject(request, out response)
{
  handleSuccess(response)
}
else
{
  handleFailure()
}
...

2

Wenn es für den Clientcode wichtig ist, den Unterschied zwischen gefunden und nicht gefunden zu kennen, und dies ein Routineverhalten sein soll, ist es am besten, null zurückzugeben. Der Client-Code kann dann entscheiden, was zu tun ist.


2

Im Allgemeinen sollte null zurückgegeben werden. Der Code, der die Methode aufruft, sollte entscheiden, ob eine Ausnahme ausgelöst oder etwas anderes versucht werden soll.


2

Oder geben Sie eine Option zurück

Eine Option ist im Grunde eine Containerklasse, die den Kunden zwingt, Standfälle zu bearbeiten. Scala hat dieses Konzept, schauen Sie sich die API an.

Dann haben Sie Methoden wie T getOrElse (T valueIfNull) für dieses Objekt, die entweder das gefundene Objekt oder eine vom Client angegebene Allternative zurückgeben.


2

Lieber null zurückgeben -

Wenn der Anrufer es ohne Überprüfung verwendet, tritt die Ausnahme trotzdem genau dort auf.

Wenn der Anrufer wirklich nicht , es verwenden, Besteuern nicht er try/ catchBlock


2

Leider ist JDK inkonsistent. Wenn Sie versuchen, auf einen nicht vorhandenen Schlüssel im Ressourcenpaket zuzugreifen, wird keine Ausnahme gefunden. Wenn Sie einen Wert von map anfordern, erhalten Sie null, wenn dieser nicht vorhanden ist. Daher würde ich die Antwort des Gewinners wie folgt ändern: Wenn der gefundene Wert null sein kann, dann eine Ausnahme auslösen, wenn er nicht gefunden wird, andernfalls null zurückgeben. Befolgen Sie also die Regel mit einer Ausnahme. Wenn Sie wissen möchten, warum der Wert nicht gefunden wird, lösen Sie immer eine Ausnahme aus.


1

Solange ein Verweis auf das Objekt zurückgegeben werden soll, sollte die Rückgabe von NULL gut sein.

Wenn es jedoch das ganze blutige Ding zurückgibt (wie in C ++, wenn Sie dies tun: 'return bla;' anstatt 'return & bla;' (oder 'bla' ist ein Zeiger), können Sie kein NULL zurückgeben, weil es ist nicht vom Typ 'Objekt'. In diesem Fall würde ich das Problem lösen, indem ich eine Ausnahme auslöse oder ein leeres Objekt zurückgebe, für das kein Erfolgsflag gesetzt ist.


1

Denken Sie nicht, dass irgendjemand den Overhead bei der Ausnahmebehandlung erwähnt hat - benötigt zusätzliche Ressourcen zum Laden und Verarbeiten der Ausnahme. Wenn es sich also nicht um ein echtes App-Killing- oder Prozessstopp-Ereignis handelt (in Zukunft würde dies mehr schaden als nützen), würde ich mich dafür entscheiden, a zurückzugeben Wert, den die aufrufende Umgebung nach eigenem Ermessen interpretieren könnte.


1

Ich stimme dem Konsens hier zu (geben Sie null zurück, wenn "nicht gefunden" ein normales mögliches Ergebnis ist, oder lösen Sie eine Ausnahme aus, wenn die Semantik der Situation erfordert, dass das Objekt immer gefunden wird).

Es gibt jedoch eine dritte Möglichkeit, die je nach Ihrer speziellen Situation sinnvoll sein kann. Ihre Methode könnte ein Standardobjekt in der Bedingung "nicht gefunden" zurückgeben, sodass der aufrufende Code sicher sein kann, dass er immer ein gültiges Objekt empfängt, ohne dass eine Nullprüfung oder ein Ausnahmefangen erforderlich ist.


1

Geben Sie eine Null zurück, Ausnahmen sind genau das: etwas, das Ihr Code tut, wird nicht erwartet.



1

Wenn die Methode eine Sammlung zurückgibt, geben Sie eine leere Sammlung zurück (wie oben angegeben). Aber bitte nicht Collections.EMPTY_LIST oder so! (im Fall von Java)

Wenn die Methode ein einzelnes Objekt abruft, haben Sie einige Optionen.

  1. Wenn die Methode immer das Ergebnis finden soll und es ein echter Ausnahmefall ist, das Objekt nicht zu finden, sollten Sie eine Ausnahme auslösen (in Java: bitte eine ungeprüfte Ausnahme)
  2. (Nur Java) Wenn Sie tolerieren können, dass die Methode eine aktivierte Ausnahme auslöst, lösen Sie eine projektspezifische ObjectNotFoundException oder ähnliches aus. In diesem Fall sagt der Compiler, dass Sie die Ausnahme vergessen haben. (Dies ist meine bevorzugte Behandlung von nicht gefundenen Dingen in Java.)
  3. Wenn Sie sagen, dass es wirklich in Ordnung ist, wenn das Objekt nicht gefunden wird und Ihr Methodenname wie findBookForAuthorOrReturnNull (..) lautet, können Sie null zurückgeben. In diesem Fall wird dringend empfohlen, eine statische Prüfung oder eine Compilerprüfung durchzuführen, die eine Dereferenzierung des Ergebnisses ohne Nullprüfung verhindert. Im Falle von Java kann es zB sein. FindBugs (siehe DefaultAnnotation unter http://findbugs.sourceforge.net/manual/annotations.html ) oder IntelliJ-Checking.

Seien Sie vorsichtig, wenn Sie eine Null zurückgeben möchten. Wenn Sie nicht der einzige Programmierer im Projekt sind, erhalten Sie zur Laufzeit NullPointerExceptions (in Java oder was auch immer in anderen Sprachen)! Geben Sie also keine Nullen zurück, die beim Kompilieren nicht überprüft werden.


Nicht, wenn der Code richtig geschrieben wurde, um zu erwarten null. Weitere Informationen finden Sie in der Antwort mit der höchsten Bewertung.
Andrew Barber

Aber nur, wenn Sie beim Kompilieren sicherstellen, dass alle Nullen überprüft werden. Dies kann mithilfe von FindBugs @NutNull auf Paketebene erfolgen und Ihre Methode als "kann null zurückgeben" markieren. Oder um eine Sprache wie Kotlin oder Nizza zu verwenden. Es ist jedoch viel einfacher, nicht null zurückzugeben.
Iuzuz

"Einfacher" vielleicht . Aber oft einfach falsch
Andrew Barber

1
Nochmals: Lesen Sie die am häufigsten gewählte Antwort, um weitere Informationen zu erhalten. Grundsätzlich gilt: Wenn das angeforderte Buch möglicherweise nicht gefunden werden kann, ist eine Ausnahme die falsch , wenn das angeforderte Buch einfach nicht gefunden wird, anstatt dass ein Fehler auftritt.
Andrew Barber

1
Sie verstehen hier viel falsch. Sie wenden bedingte Ratschläge universell an, was fast immer eine schlechte Sache ist. Lesen Sie auch den Rest der Antworten. Ihre Antwort gibt nur ein Absolut an und präsentiert eine äußerst fehlerhafte Logik dafür.
Andrew Barber

1

Wenn Sie eine Bibliothek oder eine andere Klasse verwenden, die eine Ausnahme auslöst , sollten Sie erneut werfen sie erneut . Hier ist ein Beispiel. Example2.java ist wie eine Bibliothek und Example.java verwendet das Objekt. Main.java ist ein Beispiel für diese Ausnahme. Sie sollten dem Benutzer auf der aufrufenden Seite eine aussagekräftige Nachricht und (falls erforderlich) eine Stapelverfolgung anzeigen.

Main.java

public class Main {
public static void main(String[] args) {
    Example example = new Example();

    try {
        Example2 obj = example.doExample();

        if(obj == null){
            System.out.println("Hey object is null!");
        }
    } catch (Exception e) {
        System.out.println("Congratulations, you caught the exception!");
        System.out.println("Here is stack trace:");
        e.printStackTrace();
    }
}
}

Beispiel.java

/**
 * Example.java
 * @author Seval
 * @date 10/22/2014
 */
public class Example {
    /**
     * Returns Example2 object
     * If there is no Example2 object, throws exception
     * 
     * @return obj Example2
     * @throws Exception
     */
    public Example2 doExample() throws Exception {
        try {
            // Get the object
            Example2 obj = new Example2();

            return obj;

        } catch (Exception e) {
            // Log the exception and rethrow
            // Log.logException(e);
            throw e;
        }

    }
}

Beispiel2.java

 /**
 * Example2.java
 * @author Seval
 *
 */
public class Example2 {
    /**
     * Constructor of Example2
     * @throws Exception
     */
    public Example2() throws Exception{
        throw new Exception("Please set the \"obj\"");
    }

}

Wenn die von der Funktion auszulösende Ausnahme keine Laufzeitausnahme ist und vom Aufrufer erwartet wird, dass er sie behandelt (anstatt nur das Programm zu beenden), anstatt eine Ausnahme von einem internen Subsystem auszulösen, die der Aufrufer nicht erwarten kann, Es ist besser, die interne Ausnahme mit einer externen aktivierten Ausnahme zu versehen und die interne Ausnahme zu verketten, damit jemand, der das Debugging durchführt, herausfinden kann, warum die externe Ausnahme ausgelöst wurde. Beispiel1 könnte beispielsweise 'throw new MyCheckedException ("Bitte setzen Sie das" obj "," e) "verwenden, um" e "in die ausgelöste Ausnahme aufzunehmen.
Einige Guy

0

Das hängt wirklich davon ab, ob Sie erwarten, das Objekt zu finden oder nicht. Wenn Sie der Denkschule folgen, dass Ausnahmen verwendet werden sollten, um etwas anzuzeigen, dann ist eine Ausnahme aufgetreten:

  • Objekt gefunden; Objekt zurückgeben
  • Objekt nicht gefunden; Ausnahme auslösen

Andernfalls geben Sie null zurück.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.