Ich mache mir Sorgen, dass dies eine Laufzeitausnahme ist, daher sollte es wahrscheinlich sparsam verwendet werden.
Standard-Anwendungsfall:
void setPercentage(int pct) {
if( pct < 0 || pct > 100) {
throw new IllegalArgumentException("bad percent");
}
}
Aber das scheint das folgende Design zu erzwingen:
public void computeScore() throws MyPackageException {
try {
setPercentage(userInputPercent);
}
catch(IllegalArgumentException exc){
throw new MyPackageException(exc);
}
}
Damit es wieder zu einer geprüften Ausnahme wird.
Okay, aber lass uns damit anfangen. Wenn Sie eine schlechte Eingabe machen, wird ein Laufzeitfehler angezeigt. Erstens ist es also ziemlich schwierig, diese Richtlinie einheitlich umzusetzen, da Sie möglicherweise genau das Gegenteil tun müssen:
public void scanEmail(String emailStr, InputStream mime) {
try {
EmailAddress parsedAddress = EmailUtil.parse(emailStr);
}
catch(ParseException exc){
throw new IllegalArgumentException("bad email", exc);
}
}
Und noch schlimmer: Während 0 <= pct && pct <= 100
erwartet werden kann, dass die Überprüfung des Client-Codes statisch erfolgt, gilt dies nicht für erweiterte Daten wie eine E-Mail-Adresse oder noch schlimmer für etwas, das mit einer Datenbank verglichen werden muss. Daher kann der Client-Code im Allgemeinen nicht vorab überprüft werden bestätigen.
Grundsätzlich sage ich also, dass ich keine aussagekräftige konsistente Richtlinie für die Verwendung von sehe IllegalArgumentException
. Es scheint, dass es nicht verwendet werden sollte und wir uns an unsere eigenen geprüften Ausnahmen halten sollten. Was ist ein guter Anwendungsfall, um dies zu werfen?
quelle
Wenn Sie über "schlechte Eingabe" sprechen, sollten Sie berücksichtigen, woher die Eingabe kommt.
Wird die Eingabe von einem Benutzer oder einem anderen externen System eingegeben, das Sie nicht steuern, sollten Sie erwarten, dass die Eingabe ungültig ist, und sie immer validieren. In diesem Fall ist es vollkommen in Ordnung, eine aktivierte Ausnahme auszulösen. Ihre Anwendung sollte sich von dieser Ausnahme erholen, indem sie dem Benutzer eine Fehlermeldung sendet.
Wenn die Eingabe von Ihrem eigenen System stammt, z. B. von Ihrer Datenbank oder einigen anderen Teilen Ihrer Anwendung, sollten Sie sich darauf verlassen können, dass sie gültig ist (sie sollte validiert worden sein, bevor sie dort ankam). In diesem Fall ist es vollkommen in Ordnung, eine ungeprüfte Ausnahme wie eine IllegalArgumentException auszulösen, die nicht abgefangen werden sollte (im Allgemeinen sollten Sie niemals ungeprüfte Ausnahmen abfangen). Es ist ein Programmiererfehler, dass der ungültige Wert überhaupt dort angekommen ist;) Sie müssen ihn beheben.
quelle
Because an unchecked exception is meant to be thrown as a result of a programming error
hat mir geholfen, eine Menge Sachen in meinem Kopf zuDas "sparsame" Auslösen von Laufzeitausnahmen ist keine wirklich gute Richtlinie. Effektives Java empfiehlt, dass Sie aktivierte Ausnahmen verwenden, wenn vernünftigerweise erwartet werden kann, dass der Anrufer wiederhergestellt wird . (Ein Programmiererfehler ist ein spezielles Beispiel: Wenn ein bestimmter Fall auf einen Programmiererfehler hinweist, sollten Sie eine ungeprüfte Ausnahme auslösen. Sie möchten, dass der Programmierer eine Stapelverfolgung darüber hat, wo das Logikproblem aufgetreten ist, und nicht versucht, es selbst zu behandeln.)
Wenn keine Hoffnung auf Wiederherstellung besteht, können Sie ungeprüfte Ausnahmen verwenden. Es macht keinen Sinn, sie zu fangen, also ist das vollkommen in Ordnung.
Aus Ihrem Beispiel geht jedoch nicht zu 100% hervor, in welchem Fall sich dieses Beispiel in Ihrem Code befindet.
quelle
foo(data)
könnte als Teil einer Operation durchgeführt worden sein,for(Data data : list) foo(data);
bei der der Anrufer so viele wie möglich zum Erfolg führen möchte, obwohl einige Daten fehlerhaft sind. Enthält auch programmatische Fehler. Wenn meine Anwendung fehlschlägt und eine Transaktion nicht ausgeführt wird, ist dies wahrscheinlich besser. Wenn die nukleare Kühlung offline geschaltet wird, ist dies schlecht.StackOverflowError
und dies sind Fälle, von denen der Anrufer vernünftigerweise keine Erholung erwarten kann. Es klingt jedoch so, als ob jeder Fall einer Daten- oder Anwendungslogikebene überprüft werden sollte. Das heißt, machen Sie Ihre Nullzeigerprüfungen!Wie im offiziellen Orakel-Tutorial angegeben, heißt es:
Wenn ich eine Anwendung habe, die mit der Datenbank interagiert
JDBC
, und ich eine Methode habe, die das Argument alsint item
und verwendetdouble price
. Dasprice
entsprechende Element wird aus der Datenbanktabelle gelesen. Ich multipliziere einfach die Gesamtzahl deritem
gekauften mit demprice
Wert und gebe das Ergebnis zurück. Obwohl ich immer sicher an meinem Ende bin (Application Ende) , dass der Preisfeldwert in der Tabelle kann nie negativ sein .Aber was ist, wenn der Preis - Wert kommt aus negativ ? Es zeigt, dass es ein ernstes Problem mit der Datenbankseite gibt. Möglicherweise falsche Preiseingabe durch den Betreiber. Dies ist die Art von Problem, die der andere Teil der Anwendung, der diese Methode aufruft, nicht vorhersehen und nicht beheben kann. Es ist einBUG
in Ihrer Datenbank. So undIllegalArguementException()
sollte in diesem Fall geworfen werden, der das angeben würdethe price can't be negative
.Ich hoffe, dass ich meinen Standpunkt klar zum Ausdruck gebracht habe.
quelle
Jede API sollte die Gültigkeit aller Parameter einer öffentlichen Methode überprüfen, bevor sie ausgeführt wird:
Sie stellen 99,9% der Fehler in der Anwendung dar, da nach unmöglichen Vorgängen gefragt wird. Letztendlich handelt es sich also um Fehler, die die Anwendung zum Absturz bringen sollten (es handelt sich also um einen nicht behebbaren Fehler).
In diesem Fall sollten Sie die Anwendung beenden lassen, um eine Beschädigung des Anwendungsstatus zu vermeiden.
quelle
Treat
IllegalArgumentException
als Voraussetzungen zu überprüfen, und betrachtet das Konstruktionsprinzip: Eine öffentliche Methode sollte sowohl kennen und öffentlich seine eigenen Voraussetzungen dokumentieren.Ich würde zustimmen, dass dieses Beispiel richtig ist:
Wenn EmailUtil undurchsichtig ist , was bedeutet, dass die Voraussetzungen dem Endbenutzer aus irgendeinem Grund nicht beschrieben werden können, ist eine aktivierte Ausnahme korrekt. Die zweite Version, korrigiert für dieses Design:
Wenn EmailUtil transparent ist , beispielsweise eine private Methode der betreffenden Klasse,
IllegalArgumentException
ist dies genau dann richtig, wenn die Voraussetzungen in der Funktionsdokumentation beschrieben werden können. Dies ist auch eine korrekte Version:Dieser Entwurf könnte in beide Richtungen gehen.
ParseException
. Die hier beschriebene Methode der obersten EbenescanEmail
weist darauf hin, dass der Endbenutzer beabsichtigt, nicht untersuchte E-Mails zu senden, sodass dies wahrscheinlich korrekt ist.IllegalArgumentException
. Obwohl nicht "markiert", wird die "Prüfung" in das Javadoc verschoben, um die Funktion zu dokumentieren, an die sich der Client voraussichtlich halten wird.IllegalArgumentException
Wo der Kunde nicht sagen kann, dass sein Argument im Voraus illegal ist, ist falsch.Hinweis zu IllegalStateException : Dies bedeutet, dass der interne Status dieses Objekts (private Instanzvariablen) diese Aktion nicht ausführen kann. Der Endbenutzer kann den privaten Status nicht so lose sehen, dass er Vorrang hat,
IllegalArgumentException
wenn der Clientaufruf nicht erkennen kann, dass der Status des Objekts inkonsistent ist. Ich habe keine gute Erklärung, wenn es gegenüber geprüften Ausnahmen bevorzugt wird, obwohl Dinge wie zweimaliges Initialisieren oder der Verlust einer nicht wiederhergestellten Datenbankverbindung Beispiele sind.quelle