Der Java-Compiler scheint inkonsistent zu sein, wenn Code vorhanden ist, der eindeutig keine Ausnahme auslösen kann, und Sie schreiben Umgebungscode, der erklärt, dass der Code diese Ausnahme auslösen kann.
Betrachten Sie diese Code-Snippets.
A catch
einer Ausnahme, die niemals ausgelöst wird.
Es ist Kompilierungsfehler mit Nachricht
%Vor% Eine throws
-Deklaration, die auf eine Ausnahme hinweist, die niemals ausgelöst wird.
Es kompiliert gut.
Daher zeigen die Ergebnisse des ersten Codeausschnitts, dass der Compiler berechnen kann, ob eine Methode eine in der throws
-Liste aufgelistete Ausnahme auslösen kann. Daher scheint der Compiler absichtlich keinen Fehler für das zweite Snippet zu melden. Aber warum? Warum erlaubt der Compiler das Schreiben von Exceptions in throws
section, selbst wenn der Compiler weiß, dass diese Exceptions nicht ausgelöst werden können?
Der Compiler erlaubt dies, weil die throws
-Klausel der Methode Teil der -Signatur der Methode ist und nicht Teil ihrer Implementierung . Es ist möglich, dass sich die Implementierung irgendwann ändert, während sie beibehalten wird die Unterschrift die gleiche . Eine alte Implementierung hat möglicherweise eine geprüfte Ausnahme ausgelöst, die neue jedoch möglicherweise nicht. Oder der Designer der Signatur wollte dem Implementierer möglicherweise die Flexibilität geben, eine geprüfte Ausnahme zu erzeugen, wenn dies nicht immer notwendig ist.
Da Sie andere Ansichten wollten -
Betrachten Sie zwei Implementierungen der gleichen Signatur in zwei verschiedenen Unterklassen.
Zum Beispiel (ein erfundenes Beispiel),
%Vor%Warum Compiler erlauben, Ausnahmen in Würfen Abschnitt zu schreiben, auch wenn es nicht geworfen werden kann?
Obwohl die Subklassen-Implementierung StudentDBReader
nicht IOException
wirft, muss die Elternklasse StudentLoader
immer noch throws IOException
sagen, weil andere Implementierungen von StudentLoader
sie werfen können. Obwohl die Ausnahme von der Methode nicht ausgelöst werden kann, können Sie dem Aufrufer mithilfe von StudentLoader
reference (der auf eine der beiden Unterklassen verweist) anzeigen, dass der Aufrufer diese Ausnahmen behandeln muss.
In Ihrem Snippet 1 , das die Methode g()
anzeigt, gibt es keinen Vererbungsumfang. Der Code ist genau dort im try-Block. Wenn eine Anweisung in try eine markierte Ausnahme auslöst, müssen Sie damit umgehen. Im Falle einer throws-Klausel muss der Umfang der Vererbung erlaubt sein. Der Compiler kann nicht entscheiden, welche Version von readStudentData( )
zur Laufzeit aufgerufen wird.
Ich würde erwarten, dass der Compiler im Falle von statischen Methoden einen Fehler liefert, wenn Exception in der throws-Klausel nicht geworfen wird, da statische Methoden nicht an der Vererbung teilnehmen. Ich bin nicht sicher, warum throws-Klausel in statischen Methoden Ausnahmen enthalten kann, die nie in der Implementierung geworfen werden. Es wird sowieso nicht überschrieben, also warum nicht Fehler hier werfen? Vielleicht fehlt mir etwas.
Der obige Code wird kompiliert und läuft wie in @Raedwalds Antwort erklärt.
Ich schlage das nicht als eine Antwort vor, sondern als einen Ort, an dem ich den Code veröffentlichen möchte, den ich in Kommentaren einfügen wollte.
Throws
behandelt keine Ausnahme, sie gibt die auswerfende Ausnahme nach oben an, wo die Methode aufgerufen wird. Mit anderen Worten, es wird nur eine Ausnahme an den Aufrufer übergeben.
Während try...catch
block die Ausnahme behandelt, prüft der Java-Compiler, ob eine Ausnahme zu behandeln ist, die in catch
block abgefangen wird oder nicht.
Das sind zwei verschiedene Dinge, eine ist Werfen und eine andere Handhabung die Ausnahme und der Compiler wird seine Nase nur auf die zweite kippen lassen ...: p
Aus dem JavaDoc :
Ausnahmehandler können mehr als nur Fehlermeldungen ausgeben oder anhalten das Programm. Sie können eine Fehlerkorrektur durchführen und den Benutzer auffordern, ein Entscheidung, oder propagieren den Fehler bis zu einem höheren Handler mit Verkettete Ausnahmen.
Wenn Sie also try...catch
implementation bereitstellen, fordern Sie vom Compiler an, etwas mehr zu tun, als nur die Ausnahme auszudrucken.
Ein anderer spezifischer Grund:
%Vor% Wenn Sie den kompilierten Code des obigen Beispiels nach javap -c Test.class
beobachten, werden Sie feststellen, dass eine Exception-Tabelle erstellt wird.
Wenn also der Compiler keinen Code findet, der keine Exception in try-Block wirft, liegt ein Kompilierungsfehler vor.
und Exception-Tabelle wird nicht im Fall von throws
generiert.
Tags und Links java exception-handling exception