Wann werden Throws in einer Java-Methodendeklaration verwendet?

82

Ich dachte, ich hätte ein gutes Grundverständnis für die Behandlung von Ausnahmen in Java, aber ich habe kürzlich einen Code gelesen, der mir einige Verwirrung und Zweifel bereitete. Mein Hauptzweifel, den ich hier ansprechen möchte, ist, wann eine Person Würfe in einer Java-Methodendeklaration wie der folgenden verwenden sollte:

    public void method() throws SomeException
    {
         // method body here
    }

Beim Lesen einiger ähnlicher Beiträge erfahre ich, dass Würfe als eine Art Deklaration verwendet werden, dass SomeException während der Ausführung der Methode ausgelöst werden könnte.

Meine Verwirrung kommt von einem Code, der so aussah:

     public void method() throws IOException
     {
          try
          {
               BufferedReader br = new BufferedReader(new FileReader("file.txt"));
          }
          catch(IOException e)
          {
               System.out.println(e.getMessage());
          }
     }

Gibt es einen Grund, warum Sie in diesem Beispiel einen Wurf verwenden möchten ? Es scheint, dass Sie, wenn Sie nur eine grundlegende Ausnahmebehandlung für etwas wie eine IOException durchführen, einfach den try / catch-Block benötigen und das war's.

jbranchaud
quelle

Antworten:

79

Wenn Sie einen Ausnahmetyp abfangen, müssen Sie ihn nicht auslösen, es sei denn, Sie werden ihn erneut auslösen. In dem Beispiel, das Sie veröffentlichen, sollte der Entwickler das eine oder andere getan haben, nicht beide.

Wenn Sie mit der Ausnahme nichts unternehmen, sollten Sie sie normalerweise nicht abfangen.

Das Gefährlichste, was Sie tun können, ist, eine Ausnahme zu erwischen und nichts damit zu tun.

Eine gute Diskussion darüber, wann es angebracht ist, Ausnahmen zu werfen, ist hier

Wann eine Ausnahme auslösen?

hvgotcodes
quelle
2
Sollten ungeprüfte Ausnahmen auch in der Methodensignatur mit einem "Wurf" deklariert werden, oder ist es üblich, "Würfe" nur für geprüfte Ausnahmen zu verwenden?
Cody
Diese Antwort geht nicht direkt auf den zentralen Aspekt der Frage ein: Die Verwendung des throwsSchlüsselworts.
Brent Bradburn
@hvgotcodes Was passiert, wenn ich eine Ausnahme abfange und nichts tue?
Manoj
@manoj Sie riskieren, dass Dinge kaputt gehen und Sie es nicht herausfinden können, weil wichtige Informationen verloren gehen. Es gibt Zeiten (nicht unbedingt Java), in denen es in Ordnung ist, eine Ausnahme abzufangen und nichts zu tun, aber diese sollten dokumentiert werden. In Javascript können Sie beispielsweise versuchen, Funktionen aufzurufen, die je nach Browser möglicherweise nicht vorhanden sind. Das ist nicht unbedingt ein Fehler, der Aufmerksamkeit erfordert.
Hvgotcodes
22

Sie müssen nur dann eine throw-Klausel in eine Methode einfügen, wenn die Methode eine aktivierte Ausnahme auslöst. Wenn die Methode eine Laufzeitausnahme auslöst, ist dies nicht erforderlich.

Hier finden Sie Hintergrundinformationen zu aktivierten und nicht aktivierten Ausnahmen: http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html

Wenn die Methode die Ausnahme abfängt und intern behandelt (wie in Ihrem zweiten Beispiel), muss keine throw-Klausel eingefügt werden.

Shane Bell
quelle
9

Der Code, den Sie sich angesehen haben, ist nicht ideal. Sie sollten entweder:

  1. Fangen Sie die Ausnahme ab und behandeln Sie sie. in diesem Fall throwsist das unnötig.

  2. Entfernen Sie die try/catch; In diesem Fall wird die Ausnahme von einer aufrufenden Methode behandelt.

  3. Fangen Sie die Ausnahme ab, führen Sie möglicherweise eine Aktion aus und lösen Sie die Ausnahme erneut aus (nicht nur die Nachricht).

Damo
quelle
2

Sie haben Recht, in diesem Beispiel throwsist das überflüssig. Es ist möglich, dass es von einer früheren Implementierung dort belassen wurde - vielleicht wurde die Ausnahme ursprünglich ausgelöst, anstatt im catch-Block abgefangen zu werden.

RevBingo
quelle
1

In dem von Ihnen angegebenen Beispiel löst die Methode niemals eine IOException aus, daher ist die Deklaration falsch (aber gültig). Ich vermute, dass die ursprüngliche Methode die IOException ausgelöst hat, aber dann aktualisiert wurde, um die darin enthaltene Ausnahme zu behandeln, aber die Deklaration wurde nicht geändert.

DaveJohnston
quelle
1

Der von Ihnen gepostete Code ist falsch. Er sollte eine Ausnahme auslösen, wenn eine bestimmte Ausnahme abgefangen wird, um die IOException zu behandeln, aber keine abgefangenen Ausnahmen auslösen.

Etwas wie:

public void method() throws Exception{
   try{
           BufferedReader br = new BufferedReader(new FileReader("file.txt"));
   }catch(IOException e){
           System.out.println(e.getMessage());
   }
}

oder

public void method(){
   try{
           BufferedReader br = new BufferedReader(new FileReader("file.txt"));
   }catch(IOException e){
           System.out.println("Catching IOException");
           System.out.println(e.getMessage());
   }catch(Exception e){
           System.out.println("Catching any other Exceptions like NullPontException, FileNotFoundExceptioon, etc.");
           System.out.println(e.getMessage());
   }

}}

Ignacio lucatero
quelle
1

Dies ist keine Antwort, sondern ein Kommentar, aber ich konnte keinen Kommentar mit einem formatierten Code schreiben. Hier ist der Kommentar.

Sagen wir, es gibt

public static void main(String[] args) {
  try {
    // do nothing or throw a RuntimeException
    throw new RuntimeException("test");
  } catch (Exception e) {
    System.out.println(e.getMessage());
    throw e;
  }
}

Die Ausgabe ist

test
Exception in thread "main" java.lang.RuntimeException: test
    at MyClass.main(MyClass.java:10)

Diese Methode deklariert keine "Würfe" -Ausnahmen, sondern wirft sie! Der Trick besteht darin, dass die ausgelösten Ausnahmen RuntimeExceptions (nicht aktiviert) sind, die für die Methode nicht deklariert werden müssen. Es ist ein bisschen irreführend für den Leser der Methode, da alles, was sie sieht, ein "Wurf e" ist; Anweisung, aber keine Deklaration der Throws-Ausnahme

Nun, wenn wir haben

public static void main(String[] args) throws Exception {
  try {
    throw new Exception("test");
  } catch (Exception e) {
    System.out.println(e.getMessage());
    throw e;
  }
}

Wir MÜSSEN die "Throws" -Ausnahmen in der Methode deklarieren, sonst erhalten wir einen Compilerfehler.

Αλέκος
quelle
Der Compiler führt eine überraschend ausgefeilte statische Analyse durch, um zu entscheiden, ob die throwserforderlich ist oder nicht .
Brent Bradburn