Un blocage final s'exécute-t-il même si vous lancez une nouvelle exception?

142

Dans ce code sera someVardéfini même si le bloc catch est exécuté et la deuxième exception est levée?

public void someFunction() throws Exception {
    try {
        //CODE HERE
    } catch (Exception e) {
        Log.e(TAG, "", e);
        throw new Exception(e);
    } finally {
        this.someVar= true;
    }
}
jax
la source
2
Parce qu'il y a des circonstances où le comportement n'est pas comme prévu, comme indiqué par @GaryF
jax
1
Il est à noter que le bloc final peut ne pas s'exécuter comme prévu s'il lève une exception ou effectue un retour.
Peter Lawrey

Réponses:

184

Oui, les blocs finally s'exécutent toujours ... sauf quand:

  • Le thread exécutant le bloc try-catch-finally est tué ou interrompu
  • Tu utilises System.exit(0);
  • La machine virtuelle sous-jacente est détruite d'une autre manière
  • Le matériel sous-jacent est inutilisable d'une manière ou d'une autre

De plus, si une méthode de votre bloc finally lève une exception non interceptée, rien après cela ne sera exécuté (c'est-à-dire que l'exception sera lancée comme elle le ferait dans tout autre code). Un cas très courant où cela se produit est java.sql.Connection.close().

En passant, je suppose que l'exemple de code que vous avez utilisé n'est qu'un exemple, mais faites attention à ne pas mettre la logique réelle dans un bloc finally. Le bloc finally est destiné au nettoyage des ressources (fermeture des connexions de base de données, libération des descripteurs de fichiers, etc.), et non à la logique à exécuter. S'il doit s'exécuter, faites-le avant le bloc try-catch, loin de quelque chose qui pourrait lever une exception, car votre intention est presque certainement fonctionnellement la même.

GaryF
la source
4
Qu'entendez-vous ici par "Le thread exécutant le bloc try-catch-finally est [...] interrompu"? Peut-être que la documentation est mal formulée, mais Thread.interrupt () ne fera pas sauter le bloc finally, qu'il soit jeté du bloc try ou catch. Est-ce que cela utilise «interrompu» pour signifier quelque chose de plus violent, comme Thread.stop ()?
Joe Kearney
@Joe: Oui, je pense que la documentation est un peu mal rédigée ici, et qu'elle signifie une interruption générale de l'activité du fil.
GaryF
@GaryF - Je pense que vous citez le JLS. Le libellé du JLS est parfois un peu étrange, mais vous constaterez généralement que le sens de la terminologie étrange est clairement défini ailleurs dans le document. Le JLS est une spécification et a pour objectif principal la précision (plutôt que la lisibilité).
Stephen C
1
@Stephen C - En fait, cela vient du tutoriel JavaSE (lié par d'autres). Il peut être formulé de la même manière dans le JLS, mais je ne trouve pas la partie pertinente. Je m'attendais à cela au chapitre 11 (Exceptions), au chapitre 14 (Déclarations) ou au chapitre 15 (Expressions), mais je ne vois rien qui fasse explicitement référence aux interruptions. Je serais certainement intéressé de voir cela.
GaryF
1
@GaryF - Je vois. En fait, le JLS parle de terminaison "normale" et "brusque" des instructions, et il y a une section (14.1) qui définit la terminologie. Le comportement de finallyest alors spécifié en termes de terminaisons normales et brusques.
Stephen C
10

Oui.

Consultez la documentation :

Le bloc finally s'exécute toujours lorsque le bloc try se termine.

Des exceptions:

Remarque: si la machine virtuelle Java se ferme pendant l'exécution du code try ou catch, le bloc finally peut ne pas s'exécuter. De même, si le thread exécutant le code try ou catch est interrompu ou tué, le bloc finally peut ne pas s'exécuter même si l'application dans son ensemble continue.

froadie
la source
2

Enfin, le bloc s'exécute toujours.

public class ExceptionTest {

public static void someFunction(String input) throws Exception {
    try {
        if( input.equals("ABC") ) {
            System.out.println("Matched");
        }
    } catch (Exception e) {
        throw new Exception(e);
    } finally {
        System.out.println("Input Is "+input+" Finally Executed!!!");
    }
}

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    try {
        System.out.println("********* Test with VALUE ********* ");
        someFunction("ABC");
        System.out.println("\r\n********* Test with NULL  ********* ");
        someFunction(null);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}

Java Try Catch Enfin Bloquer avec Lancer

Vasanth Umapathy
la source
2

Enfin est toujours exécuté, quel que soit votre cas ie

  • bloc try-catch-finally
  • jette

Pour les exceptions non vérifiées, java n'impose pas de gestion des erreurs. ceci étant la raison, si une exception non vérifiée se produit dans le bloc finally et qu'aucune manipulation n'est effectuée pour cela, alors le code écrit en dessous de ce point (où l'erreur s'est produite) ne sera pas exécuté.

Je suggère donc de toujours gérer toutes les exceptions, qu'elles soient cochées ou décochées. De cette façon, vous pouvez vous assurer que le bloc de code dans finally est également exécuté, peu importe si une exception non cochée se produit également. vous avez une place dans la capture de sous-nid et le bloc Enfin pour faire le travail nécessaire.

yug
la source
1

Oui. finallyblock s'exécute toujours sauf dans le cas où vous appelez System.exit () car il arrête Java VM.

Vladimir Ivanov
la source
Les hooks d'arrêt sont toujours appelés après System.exit (), mais les threads non système existants sont tous arrêtés.
Peter Lawrey