2016-01-15 6 views
6

Im folgenden Code-Block:Was genau wird in einer erweiterten Try-with-Resources-Anweisung gefangen?

try (/* resources declaration */) { 
    // some dangerous code 
} catch (Exception e) { 
    // error handling and reporting 
} 

Was passiert, wenn sowohl der Code innerhalb des try Blockes und die automatischen close() Erklärung warf Ausnahmen passieren würde? Welche würde man im catch Block erwischen? Beide? Nur einer von ihnen? Wenn ja, welcher?

Außerdem was ist, wenn die try ist erfolgreich, aber die close nicht? Wird der Catch-Block eingegeben?

Antwort

6

aus dem Abschnitt JLS Zitiert 14.20.3.1:

In einem grundlegenden Try-with-Ressourcen-Anweisung, die eine einzelne Ressource verwaltet:

  • Wenn die Initialisierung der Ressource abrupt wegen eines throw abgeschlossen eines Wertes V, dann wird die try-with-resources-Anweisung abrupt wegen eines throw des Werts V abgeschlossen.
  • Wenn die Initialisierung der Ressource normalerweise abgeschlossen ist, und der try Block beendet abrupt wegen eines throw eines Wertes V, dann:

    • Wenn die automatische Schließung der Ressource normalerweise abgeschlossen ist, dann den Versuch -with-resources-Anweisung wird abrupt wegen eines throw des Werts V abgeschlossen.

    • Wenn die automatische Schließung der Ressource aufgrund eines throw eines Wertes abrupt beendet V2, dann wird der Try-with-Ressourcen Anweisung abgeschlossen abrupt wegen eines throw Wert V mit V2 hinzugefügt, um die unterdrückt Ausnahmeliste von V .

  • Wenn die Initialisierung der Ressource normalerweise abgeschlossen ist, und der try Block normalerweise abgeschlossen, und die automatische Schließung der Ressource abgeschlossen abrupt wegen eines Wurfes eines Wertes V, dann wird die Try-with-Ressourcen Anweisung abgeschlossen abrupt wegen eines throw des Wertes V.

Das bedeutet, dass, wenn sowohl der Code innerhalb des try Blockes und die automatischen close() Anweisung eine Ausnahme auslösen, der catch Teil der Ausnahme von dem try Block, mit Ausnahme von close() im suppressed exceptions geworfen geworfen behandelt .

Das bedeutet auch, dass, wenn der try Block erfolgreich ist, aber die automatischen close() ausfällt, wird die catch ausgeführt werden Schweller und die catched Ausnahme wird die Ausnahme von close() geworfen werden.


Hier ist ein Test, dieses Verhalten zu überprüfen:

public class Main { 
    public static void main(String[] args) throws Exception { 
     // try block fails and close() fails 
     try (T t = new T()) { 
      throw new Exception("thrown by try part"); 
     } catch (Exception e) { 
      System.out.println(e.getMessage()); 
      System.out.println(e.getSuppressed()[0].getMessage()); 
     } 

     // try block is successful but close() fails 
     try (T t = new T()) { 
      // 
     } catch (Exception e) { 
      System.out.println(e.getMessage()); 
     } 
    } 
} 

class T implements AutoCloseable { 
    @Override 
    public void close() throws Exception { 
     throw new Exception("thrown by close"); 
    } 
} 

Dieser Code

thrown by try part 
thrown by close 
thrown by close 

was bedeutet, dass die catched Ausnahme war die Ausnahme von der try Teil des Codes geworfen gedruckt wird für Der erste Teil. Für den zweiten Teil war die catched-Ausnahme in der Tat die Ausnahme, die von close() ausgelöst wurde.

-1

Die in den try-Block geworfene Ausnahme wird nach außen geworfen.

Während mit dem try-catch-finally die Ausnahme aus dem finally-Block geworfen wurde, würde der Call-Stack weiterverbreitet werden.

InputStream input = null; 

    try { 
     input = new FileInputStream("file.txt"); 

     int data = input.read(); 
     while(data != -1){ 
      System.out.print((char) data); 
      data = input.read(); 
     } 
    } finally { 
     if(input != null){ 
      input.close(); 
     } 
    } 

In diesem Fall, wenn eine Ausnahme sowohl im Block Versuch auftritt, und der schließlich blockieren (wenn die Input geschlossen ist), der die letzte geworfen wird, auch wenn die Ausnahme von dem try-Block geworfen würde wahrscheinlich für die Propagierung relevanter sein.

try(FileInputStream input = new FileInputStream("file.txt")) { 

     int data = input.read(); 
     while(data != -1){ 
      System.out.print((char) data); 
      data = input.read(); 
     } 
    } 

in diesem Fall zwar, wenn eine Ausnahme in tritt sowohl in der try-Block und der finally-Block wird der erste

+0

Es gibt eine catch-Anweisung propagiert, die durch die 'try' geworfen, die Ausnahmen behandelt. Ich weiß nicht, wie diese Ausnahmen in die Außenwelt geworfen werden. –

+0

Wenn die verschließbare Ressource beim Schließen eine Ausnahme auslöst, ist die im try-Block aufgetretene Ausnahme relevanter. Daher wird sie propagiert – Chris

+0

Bitte lesen Sie die Frage noch einmal, schauen Sie, dass OP eindeutig besagt, dass ** eine 'catch'-Anweisung verwendet wird ** –