2011-01-12 7 views
1

Heute bei der Arbeit musste ich ein Code-Snippet überprüfen, das diesem Mock-Beispiel ähnelt.Verhalten von verschachtelten schließlich in Ausnahmen

package test;

import java.io.IOException; 
import org.apache.log4j.Logger; 

public class ExceptionTester { 

    public static Logger logger = Logger.getLogger(ExceptionTester.class); 

public void test() throws IOException { 
    new IOException(); 
} 

public static void main(String[] args) { 
    ExceptionTester comparator = new ExceptionTester(); 
    try { 
     try { 
      comparator.test(); 
     } finally { 
      System.out.println("Finally 1"); 
     } 
    } catch(IOException ex) { 
     logger.error("Exception happened" ex); 
      // also close opened resources 
    } 
    System.out.println("Exiting out of the program"); 
} 

}

Es ist die folgende output.I Druck zu erwarten, da die inneren try einen Compiler-Fehler keinen catch Block hat.

 
Finally 1 
Exiting out of the program 

Ich verstehe nicht, warum IOException durch die äußere catch Block abgefangen wird. Ich würde es begrüßen, wenn jemand das erklären kann, vor allem mit dem Hinweis auf Stapel Abwickelprozesses

+4

Ein 'try' muss> = 1' catch' __und/oder__ ein 'finally' haben. Der 'catch' ist nicht erforderlich. – dkarp

Antwort

6

Ein finally Block stellt eine Aufgabe dar, die sowohl unter normalen als auch unter anormalen Bedingungen ausgeführt werden muss.

Beispiel: Sie nehmen einen Interviewkandidaten zum Mittagessen. Während des Mittagessens erfahren Sie, dass er wegen Mordes von der Polizei gesucht wird. Ausnahme! Das Mittagessen ist vorbei, das Interview ist ein totaler Verlust, aber ... Sie müssen immer noch für das Mittagessen bezahlen.

try { 
    meetForLunch(interviewCandidate); 
} 
finally { 
    lunchBill.pay(); 
} 

Beachten Sie, dass für das Mittagessen zu bezahlen hat die Ausnahme nicht gekümmert, hätte man noch etwas über den Mörder in Ihrem Interview zu tun. Es ist nur ein losen Ende, vor der Verarbeitung mit Schadensbegrenzung gesorgt werden muss.

meisten schließlich Blöcke in dieser Weise verwendet werden: Eine Datei geschlossen werden muss, ob die Daten erfolgreich gespeichert oder nicht, muss eine Datenbankverbindung geschlossen werden, ob die Transaktion genehmigt wurde oder nicht, usw.

Und die Ausnahme geht auf ihrem fröhlichen Weg nach außen und sucht nach einem passenden Catch-Block in einem einschließenden Scope.

Beachten Sie, dass Blöcke abschließend immer ausgeführt werden, es sei denn der Prozess endet, während der try-Block noch ausgeführt wird.

+0

Natürlich bricht diese Analogie zusammen, wenn der Kandidat Sie beim Mittagessen ermordet. :-) –

+5

@Stephen: Ich glaube, du hast den letzten Satz verpasst. –

+0

@Ben Voight - soweit das Restaurant betroffen ist, ist der Prozess nicht beendet. –

0

Ich denke, das Problem ist, dass Ihre Funktion

public void test() throws IOException { 
    new IOException(); 
} 

eigentlich nicht eine Ausnahme werfen - es schafft nur ein neues IOException() Objekt. Ändern Sie dies zu

public void test() throws IOException { 
    throw new IOException(); 
} 

sollte dies beheben.

+1

Deshalb wurde "Ausnahme passiert" nicht gedruckt, aber es hat keinen Einfluss auf den "finally" -Block. –

0

Der Code über erfordert nicht viel einer Erklärung - nicht definitiv Call-Stacks !. Was ist deine Verwirrung, habe ich etwas übersehen? Hier ist meine Erklärung

Erster Punkt

  • Sie brauchen nicht beide einen Haken und ein schließlich blockieren. Sie können einen von oder beide von ihnen mit einem try-Block haben, aber nicht von ihnen.
  • Der Code in der finally-Klausel wird immer ausgeführt, auch wenn eine Ausnahme innerhalb des try oder catch-Blocks ausgelöst wird.Wenn Ihr Code eine Rückgabeanweisung innerhalb des try oder catch-Blocks hat, wird der Code innerhalb des finally-blocks ausgeführt, bevor er von der Methode zurückkehrt.

So in dem obigen Code, wurde eine Ausnahme nie geworfen (weil Sie nicht throw im test() Methode verwendet werden) jedoch , bekam finally Block ausgeführt, wie durch die der Sprache spec versprochen und man bekam die Ausgabe Finally 1. Die nächste Anweisung in der Ausführungsreihenfolge lautet System.out.println("Exiting out of the program");, da der catch-Block nie erreicht wird, da keine IOExceptions vorhanden sind. So wird Exiting out of the program gedruckt.