Warum lässt der Java-Compiler Ausnahmen zu, die im Wrows-Abschnitt aufgelistet werden und die Methode nicht auslösen kann?

8

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.

Snippet 1

A catch einer Ausnahme, die niemals ausgelöst wird.

%Vor%

Es ist Kompilierungsfehler mit Nachricht

%Vor%

Snippet2

Eine throws -Deklaration, die auf eine Ausnahme hinweist, die niemals ausgelöst wird.

%Vor%

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?

    
gstackoverflow 24.03.2014, 13:26
quelle

5 Antworten

10

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.

    
Raedwald 24.03.2014, 13:38
quelle
0

Nur ein Versuch !!

Für den zweiten Fall besteht die Möglichkeit, dass eine andere Klasse diese Methode in der Zukunft überschreibt und ein Code in das geschrieben wird, der diese Ausnahme auslösen kann.

    
RKC 24.03.2014 13:33
quelle
0

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.

    
RuntimeException 24.03.2014 14:08
quelle
0
%Vor%

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.

    
Germann Arlington 24.03.2014 14:36
quelle
0

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.

%Vor%

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.

    
Not a bug 24.03.2014 13:42
quelle