Un bloc enfin est-il toujours exécuté en Java?


2382

Compte tenu de ce code, puis-je être absolument sûr que le finallybloc s'exécute toujours, quel qu'il something()soit?

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("I don't know if this will get printed out");
}

473
Si ce n'est pas le cas, le mot clé doit être nommé à la probablyplace.
Noon Silk




27
@BinoyBabu, finaliseur ! = finally; finalizer == la finalize()méthode.
jaco0646

Réponses:


2699

Oui, finallysera appelé après l'exécution des blocs de code tryou catch.

Les seules heures finallyqui ne seront pas appelées sont:

  1. Si vous invoquez System.exit()
  2. Si vous invoquez Runtime.getRuntime().halt(exitStatus)
  3. Si la JVM plante en premier
  4. Si la machine virtuelle Java atteint une boucle infinie (ou une autre instruction non interruptible et sans terminaison) dans le bloc tryorcatch
  5. Si le système d'exploitation met fin de force au processus JVM; par exemple, kill -9 <pid>sous UNIX
  6. Si le système hôte meurt; par exemple, panne de courant, erreur matérielle, panique du système d'exploitation, et cetera
  7. Si le finallybloc va être exécuté par un thread démon et que tous les autres threads non démons se terminent avant, finallyest appelé

44
En fait, thread.stop()n'empêche pas nécessairement l' finallyexécution du bloc.
Piotr Findeisen

181
Que diriez-vous que nous disons que le finallybloc sera appelé après le trybloc et avant que le contrôle ne passe aux instructions suivantes. Cela est cohérent avec le bloc try impliquant une boucle infinie et donc le bloc finalement jamais réellement invoqué.
Andrzej Doyle

9
il y a aussi un autre cas, lorsque nous utilisons des blocs try-catch-finally
imbriqués

7
enfin, finalement block n'est pas appelé en cas d'exception levée par le thread démon.
Amrish Pandey

14
@BinoyBabu - Il s'agit du finaliseur, pas finalement du bloc
avmohan

567

Exemple de code:

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int test() {
    try {
        return 0;
    }
    finally {
        System.out.println("finally trumps return.");
    }
}

Production:

finally trumps return. 
0

18
Pour info: en C # le comportement est identique à part le fait que le remplacement de l'instruction dans la finallyclause- return 2;n'est pas autorisé (Compiler-Error).
Alexander Pacha

15
Voici un détail important à connaître: stackoverflow.com/a/20363941/2684342
WoodenKitty

18
Vous pouvez même ajouter une instruction return dans le bloc finally lui-même, qui remplacera alors la valeur de retour précédente. Cela supprime également par magie les exceptions non gérées. À ce stade, vous devriez envisager de refactoriser votre code.
Zyl

8
Cela ne prouve pas vraiment que finalement l'emporte sur le retour. La valeur de retour est imprimée à partir du code appelant. Cela ne semble pas prouver grand-chose.
Trimtab

20
Désolé, mais ceci n'est pas une preuve. Ce n'est une preuve que si vous pouvez montrer que cet exemple se comporte toujours de cette façon sur toutes les plates-formes Java ET que des exemples similaires se comportent également toujours de cette façon.
Stephen C

391

De plus, bien que ce soit une mauvaise pratique, s'il y a une instruction return dans le bloc finally, elle l'emportera sur tout autre retour du bloc normal. Autrement dit, le bloc suivant retournerait faux:

try { return true; } finally { return false; }

Même chose avec le lancement d'exceptions du bloc finally.


95
C'est vraiment une mauvaise pratique. Voir stackoverflow.com/questions/48088/… pour plus d'informations sur les raisons de son mauvais fonctionnement.
John Meagher

23
D'accord. Un retour en dedans enfin {} ignore toute exception levée dans try {}. Effrayant!
neu242

8
@ dominicbri7 Pourquoi pensez-vous que c'est une meilleure pratique? Et pourquoi devrait-il en être autrement lorsque la fonction / méthode est nulle?
corsiKa

8
Pour la même raison, je n'utilise JAMAIS les goto dans mes codes C ++. Je pense que les retours multiples le rendent plus difficile à lire et plus difficile à déboguer (bien sûr, dans les cas très simples, cela ne s'applique pas). Je suppose que c'est juste une préférence personnelle et à la fin, vous pouvez réaliser la même chose en utilisant l'une ou l'autre méthode
dominicbri7

16
J'ai tendance à utiliser un certain nombre de retours quand une sorte de cas exceptionnel se produit. Comme si (il y a une raison de ne pas continuer) de revenir;
iHearGeoff

257

Voici les mots officiels de la spécification du langage Java.

14.20.2. Exécution de try-finally et try-catch-finally

Une tryinstruction avec un finallybloc est exécutée en exécutant d'abord le trybloc. Ensuite, il y a le choix:

  • Si l'exécution du try bloc se termine normalement, [...]
  • Si l'exécution du trybloc se termine brutalement à cause throwd'une valeur V , [...]
  • Si l'exécution du trybloc se termine brutalement pour toute autre raison R , alors le finallybloc est exécuté. Ensuite, il y a le choix:
    • Si le bloc finalement se termine normalement, alors l' tryinstruction se termine brusquement pour la raison R .
    • Si le finallybloc se termine brusquement pour la raison S , alors l' tryinstruction se termine brusquement pour la raison S ( et la raison R est rejetée ).

La spécification de returnrend cela explicite:

JLS 14.17 La déclaration de retour

ReturnStatement:
     return Expression(opt) ;

Une returndéclaration sans Expression tentatives de transfert de contrôle à l'appelant de la méthode ou du constructeur qui le contient.

Une returndéclaration avec une Expression tentative de transfert du contrôle à l'invocateur de la méthode qui le contient; la valeur de laExpression devient la valeur de l'appel de méthode.

Les descriptions précédentes disent " tente de transférer le contrôle " plutôt que simplement " transfère le contrôle " car s'il y a destryinstructions dans la méthode ou le constructeur dont lestryblocs contiennent l'returninstruction, alors toutes lesfinallyclauses de cestryinstructions seront exécutées, dans l'ordre, du plus interne au plus externe , avant que le contrôle ne soit transféré à l'appelant de la méthode ou du constructeur. L'achèvement brutal d'unefinallyclause peut perturber le transfert de contrôle initié par unereturndéclaration.


163

En plus des autres réponses, il est important de souligner que «finalement» a le droit de remplacer toute exception / valeur retournée par le bloc try..catch. Par exemple, le code suivant renvoie 12:

public static int getMonthsInYear() {
    try {
        return 10;
    }
    finally {
        return 12;
    }
}

De même, la méthode suivante ne lève pas d'exception:

public static int getMonthsInYear() {
    try {
        throw new RuntimeException();
    }
    finally {
        return 12;
    }
}

Alors que la méthode suivante le lance:

public static int getMonthsInYear() {
    try {
        return 12;          
    }
    finally {
        throw new RuntimeException();
    }
}

63
Il convient de noter que le cas du milieu est précisément la raison pour laquelle avoir une déclaration de retour à l'intérieur d'un bloc finally est absolument horrible (cela pourrait cacher tout Throwable).
Dimitris Andreou

2
Qui ne veut pas d'un surpressé OutOfMemoryError? ;)
RecursiveExceptionException

Je l'ai testé et il supprime une telle erreur (ouais!). Il génère également un avertissement lorsque je le compile (ouais!). Et vous pouvez contourner cela en définissant une variable de retour, puis en utilisant return retVal après le finallybloc, bien que cela suppose bien sûr que vous ayez supprimé certaines autres exceptions car le code n'aurait pas de sens autrement.
Maarten Bodewes

120

J'ai essayé l'exemple ci-dessus avec une légère modification-

public static void main(final String[] args) {
    System.out.println(test());
}

public static int test() {
    int i = 0;
    try {
        i = 2;
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
    }
}

Le code ci-dessus génère:

l'emporte enfin sur le retour.
2

C'est parce que quand return i;est exécuté ia une valeur 2. Après cela, le finallybloc est exécuté où 12 est assigné à ipuis System.outout est exécuté.

Après avoir exécuté le finallybloc, letry bloc renvoie 2, au lieu de renvoyer 12, car cette instruction de retour n'est pas exécutée à nouveau.

Si vous déboguez ce code dans Eclipse, vous aurez l'impression qu'après l'exécution System.outdu finallybloc, l' returninstruction de trybloc est exécutée à nouveau. Mais ce n'est pas le cas. Il renvoie simplement la valeur 2.


10
Cet exemple est génial, il ajoute quelque chose qui n'a pas été mentionné dans des dizaines de threads finalement liés. Je pense que pratiquement aucun développeur ne le sait.
Espérons que le

4
Et si ce in'était pas un objet primitif, mais un objet Entier.
Yamcha

J'ai du mal à comprendre ce cas. docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.17 indique que «une instruction de retour avec une expression tente de transférer le contrôle à l'invocateur de la méthode ou du corps lambda qui contient it .... Si l'évaluation de l'expression se termine normalement, produisant une valeur V .. " n'affecte pas la valeur retournée, corrigez-moi.
meexplorer

Mais je n'ai trouvé aucune preuve à ce sujet, où est-il mentionné que le retour n'évalue pas à nouveau l'expression.
meexplorer

1
@meexplorer un peu en retard, mais cela est expliqué dans JLS 14.20.2. Exécution de try-finally et try-catch-finally - libellé un peu compliqué, 14.17. La déclaration de retour doit également être lue
user85421

117

Voici une élaboration de la réponse de Kevin . Il est important de savoir que l'expression à renvoyer est évaluée avant finally, même si elle est retournée après.

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int printX() {
    System.out.println("X");
    return 0;
}

public static int test() {
    try {
        return printX();
    }
    finally {
        System.out.println("finally trumps return... sort of");
    }
}

Production:

X
finally trumps return... sort of
0

8
Important à savoir.
Aminadav Glickshtein

Bon à savoir et aussi logique. Il semble que le retour de la valeur du retour soit ce qui vient après finally. Le calcul de la valeur de retour ( printX()ici) précède toujours.
Albert

un bon exemple avec les 3 points "retour"!
radistao

Nan. Le code ci-dessus devrait être remplacé System.out.println("finally trumps return... sort of");parSystem.out.print("finally trumps return in try"); return 42;
Pacerier

54

C'est toute l'idée d'un bloc enfin. Il vous permet de vous assurer que vous effectuez des nettoyages qui pourraient autrement être ignorés car vous revenez, entre autres, bien sûr.

Est finalement appelé indépendamment de ce qui se passe dans le bloc try (à moins que vous n'appeliez System.exit(int)ou que la machine virtuelle Java ne démarre pour une autre raison).


C'est une réponse extrêmement faible. stackoverflow.com/a/65049/715269
Gangnus

42

Une façon logique d'y penser est:

  1. Le code placé dans un bloc finally doit être exécuté quoi qu'il se passe dans le bloc try
  2. Donc, si le code du bloc try tente de renvoyer une valeur ou de lever une exception, l'élément est placé «sur l'étagère» jusqu'à ce que le bloc finally puisse s'exécuter
  3. Parce que le code dans le bloc finally a (par définition) une priorité élevée, il peut retourner ou jeter ce qu'il veut. Dans ce cas, tout ce qui reste «sur l'étagère» est jeté.
  4. La seule exception à cela est si la machine virtuelle s'arrête complètement pendant le bloc try, par exemple par 'System.exit'

10
Est-ce juste "une façon logique d'y penser" ou est-ce vraiment la façon dont le bloc enfin est censé fonctionner selon les spécifications? Un lien vers une ressource Sun serait très intéressant ici.
matias

21

enfin est toujours exécuté sauf en cas de fin anormale du programme (comme appeler System.exit (0) ..). donc, votre sysout sera imprimé



18

Le bloc finally est toujours exécuté sauf en cas de fin anormale du programme, résultant soit d'un crash de la JVM, soit d'un appel à System.exit(0).

En plus de cela, toute valeur renvoyée à l'intérieur du bloc finally remplacera la valeur retournée avant l'exécution du bloc finally, alors faites attention à vérifier tous les points de sortie lorsque vous utilisez try enfin.


18

Non, pas toujours un cas d'exception est // System.exit (0); avant que le bloc finalement empêche finalement d'être exécuté.

  class A {
    public static void main(String args[]){
        DataInputStream cin = new DataInputStream(System.in);
        try{
            int i=Integer.parseInt(cin.readLine());
        }catch(ArithmeticException e){
        }catch(Exception e){
           System.exit(0);//Program terminates before executing finally block
        }finally{
            System.out.println("Won't be executed");
            System.out.println("No error");
        }
    }
}

Et c'est l'une des raisons pour lesquelles vous ne devriez jamais appeler System.exit () ...
Franz D.

13

Enfin est toujours exécuté, c'est tout le point, juste parce qu'il apparaît dans le code après le retour ne signifie pas que c'est comme ça qu'il est implémenté. Le runtime Java a la responsabilité d'exécuter ce code lors de la sortie du trybloc.

Par exemple, si vous disposez des éléments suivants:

int foo() { 
    try {
        return 42;
    }
    finally {
        System.out.println("done");
    }
}

Le runtime va générer quelque chose comme ceci:

int foo() {
    int ret = 42;
    System.out.println("done");
    return 42;
}

Si une exception non interceptée est levée, le finallybloc s'exécute et l'exception continue de se propager.


11

En effet, vous avez affecté la valeur de i à 12, mais vous n'avez pas renvoyé la valeur de i à la fonction. Le code correct est le suivant:

public static int test() {
    int i = 0;
    try {
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
        return i;
    }
}

10

Parce qu'un bloc finally sera toujours appelé à moins que vous n'appeliez System.exit()(ou que le thread ne plante).


10

De manière concise, dans la documentation Java officielle (cliquez ici ), il est écrit que -

Si la JVM 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.


10

La réponse est simple OUI .

CONTRIBUTION:

try{
    int divideByZeroException = 5 / 0;
} catch (Exception e){
    System.out.println("catch");
    return;    // also tried with break; in switch-case, got same output
} finally {
    System.out.println("finally");
}

PRODUCTION:

catch
finally

1
La réponse est simple NON.
Christophe Roussy

1
@ChristopheRoussy Comment? Pouvez-vous expliquer s'il vous plaît?
Rencontrez

1
lire la réponse acceptée, la question initiale porte sur «Est-ce que ça va toujours exécuter» et ça ne sera pas toujours. Dans votre cas, ce sera le cas mais cela ne répond pas à la question d'origine et peut même induire les débutants en erreur.
Christophe Roussy

alors dans quel cas il ne sera pas exécuté?
Rencontrez

Dans tous les cas mentionnés dans d'autres réponses, voir la réponse acceptée avec plus de 1000 votes positifs.
Christophe Roussy

9

Oui, il sera appelé. C'est tout l'intérêt d'avoir un mot-clé enfin. Si sauter hors du bloc try / catch pouvait simplement sauter le bloc finalement, c'était la même chose que de mettre System.out.println en dehors du try / catch.


9

Oui, enfin le bloc est toujours exécuté. La plupart des développeurs utilisent ce bloc pour fermer la connexion à la base de données, l'objet d'ensemble de résultats, l'objet d'instruction et les utilisent également dans l'hibernation java pour annuler la transaction.


9

PAS TOUJOURS

La spécification du langage Java décrit comment try- catch- finallyet try- catchblocs fonctionnent à 14.20.2
En aucun endroit , il précise que le finallybloc est toujours exécuté. Mais pour tous les cas où la try- catch- finallyet try- des finallyblocs complets , il ne précise que , avant la fin finallydoit être exécuté.

try {
  CODE inside the try block
}
finally {
  FIN code inside finally block
}
NEXT code executed after the try-finally block (may be in a different method).

Le JLS ne garantit pas que FIN est exécuté après CODE . Le JLS garantit que si CODE et NEXT sont exécutés, FIN sera toujours exécuté après CODE et avant NEXT .

Pourquoi le JLS ne garantit-il pas que le finallybloc est toujours exécuté après le trybloc? Parce que c'est impossible. Il est peu probable mais possible que la JVM soit abandonnée (kill, crash, power off) juste après la fin du trybloc mais avant l'exécution du finallybloc. Il n'y a rien que le JLS puisse faire pour éviter cela.

Ainsi, tout logiciel qui, pour son bon comportement, dépend des finallyblocs toujours exécutés une fois leurs tryblocs terminés est buggé.

returnles instructions dans le trybloc ne sont pas pertinentes pour ce problème. Si l'exécution atteint le code après le try- catch- finallyil est garanti que le finallybloc aura été exécuté avant, avec ou sans returninstructions à l'intérieur du trybloc.


8

Oui, il sera. Peu importe ce qui se passe dans votre bloc try ou catch, à moins que System.exit () ne soit appelé ou que JVM ne plante. s'il y a une instruction de retour dans le (s) bloc (s), finalement sera exécutée avant cette instruction de retour.


8

Oui, il sera. Le seul cas où ce ne sera pas le cas, c'est que la JVM se ferme ou se bloque


8

Ajouter à la réponse de @ vibhash car aucune autre réponse n'explique ce qui se passe dans le cas d'un objet mutable comme celui ci-dessous.

public static void main(String[] args) {
    System.out.println(test().toString());
}

public static StringBuffer test() {
    StringBuffer s = new StringBuffer();
    try {
        s.append("sb");
        return s;
    } finally {
        s.append("updated ");
    }
}

Sortira

sbupdated 

Depuis Java 1.8.162, ce n'est pas la sortie.
Sam

8

J'ai essayé, c'est un filetage simple.

public static void main(String args[]) throws Exception {
    Object obj = new Object();
    try {
        synchronized (obj) {
            obj.wait();
            System.out.println("after wait()");
        }
    } catch (Exception ignored) {
    } finally {
        System.out.println("finally");
    }
}

Le main Threadsera en waitétat pour toujours, donc finallyne sera jamais appelé ,

donc la sortie de la console ne sera pas print String: après wait()oufinally

En accord avec @Stephen C, l'exemple ci-dessus est l'un des troisièmes cas mentionnés ici :

Ajout d'autres possibilités de boucle infinie dans le code suivant:

// import java.util.concurrent.Semaphore;

public static void main(String[] args) {
    try {
        // Thread.sleep(Long.MAX_VALUE);
        // Thread.currentThread().join();
        // new Semaphore(0).acquire();
        // while (true){}
        System.out.println("after sleep join semaphore exit infinite while loop");
    } catch (Exception ignored) {
    } finally {
        System.out.println("finally");
    }
}

Cas 2: si la JVM plante en premier

import sun.misc.Unsafe;
import java.lang.reflect.Field;

public static void main(String args[]) {
    try {
        unsafeMethod();
        //Runtime.getRuntime().halt(123);
        System.out.println("After Jvm Crash!");
    } catch (Exception e) {
    } finally {
        System.out.println("finally");
    }
}

private static void unsafeMethod() throws NoSuchFieldException, IllegalAccessException {
    Field f = Unsafe.class.getDeclaredField("theUnsafe");
    f.setAccessible(true);
    Unsafe unsafe = (Unsafe) f.get(null);
    unsafe.putAddress(0, 0);
}

Réf: Comment planter une JVM?

Cas 6: Si le finallybloc va être exécuté par le démon Threadet que toutes les autres sorties non démon Threadsavant finallysont appelées.

public static void main(String args[]) {
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                printThreads("Daemon Thread printing");
                // just to ensure this thread will live longer than main thread
                Thread.sleep(10000);
            } catch (Exception e) {
            } finally {
                System.out.println("finally");
            }
        }
    };
    Thread daemonThread = new Thread(runnable);
    daemonThread.setDaemon(Boolean.TRUE);
    daemonThread.setName("My Daemon Thread");
    daemonThread.start();
    printThreads("main Thread Printing");
}

private static synchronized void printThreads(String str) {
    System.out.println(str);
    int threadCount = 0;
    Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
    for (Thread t : threadSet) {
        if (t.getThreadGroup() == Thread.currentThread().getThreadGroup()) {
            System.out.println("Thread :" + t + ":" + "state:" + t.getState());
            ++threadCount;
        }
    }
    System.out.println("Thread count started by Main thread:" + threadCount);
    System.out.println("-------------------------------------------------");
}

sortie: Ceci n'imprime pas "finalement" ce qui implique que "Enfin bloquer" dans "thread démon" ne s'est pas exécuté

main Thread Printing  
Thread :Thread[My Daemon Thread,5,main]:state:BLOCKED  
Thread :Thread[main,5,main]:state:RUNNABLE  
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE   
Thread count started by Main thread:3  
-------------------------------------------------  
Daemon Thread printing  
Thread :Thread[My Daemon Thread,5,main]:state:RUNNABLE  
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE  
Thread count started by Main thread:2  
-------------------------------------------------  

Process finished with exit code 0

4
Voir la réponse acceptée. Ceci est juste un cas de bord de "boucle infinie".
Stephen C

8

Considérez le programme suivant:

public class SomeTest {

    private static StringBuilder sb = new StringBuilder();

    public static void main(String args[]) {

        System.out.println(someString());
        System.out.println("---AGAIN---");
        System.out.println(someString());
        System.out.println("---PRINT THE RESULT---");
        System.out.println(sb.toString());
    }

    private static String someString() {

        try {
            sb.append("-abc-");
            return sb.toString();

        } finally {
            sb.append("xyz");
        }
    }
}

Depuis Java 1.8.162, le bloc de code ci-dessus donne la sortie suivante:

-abc-
---AGAIN---
-abc-xyz-abc-
---PRINT THE RESULT---
-abc-xyz-abc-xyz

cela signifie que l'utilisation finallypour libérer des objets est une bonne pratique comme le code suivant:

private static String someString() {

    StringBuilder sb = new StringBuilder();

    try {
        sb.append("abc");
        return sb.toString();

    } finally {
        sb = null; // Just an example, but you can close streams or DB connections this way.
    }
}

Cela ne devrait-il pas être sb.setLength(0)enfin?
user7294900

sb.setLength (0) videra simplement les données dans le StringBuffer. Donc, sb = null dissociera l'objet de la référence.
Sam

"Xyz" ne doit-il pas être imprimé deux fois dans la sortie? Puisque la fonction a été appelée deux fois, pourquoi "finalement" ne l'a été qu'une seule fois?
fresko

2
Ce n'est pas une bonne pratique. Ce bloc enfin avec sb = null;juste ajoute du code inutile. Je comprends que vous voulez dire qu'un finallybloc est un bon endroit pour libérer des ressources comme une connexion à une base de données ou quelque chose comme ça, mais gardez à l'esprit que votre exemple pourrait confondre les nouveaux arrivants.
Roc Boronat

1
@Samim Merci, j'ai ajouté les lignes System.out.println("---AGAIN2---"); System.out.println(sb);et c'est plus clair maintenant. En l'état, la sortie était contraire à votre thèse: p J'ai également ajouté à votre réponse, mais la modification doit être acceptée par un modérateur ou quelqu'un comme ça. Sinon, vous pouvez les ajouter
fresko

7

C'est en fait vrai dans n'importe quel langage ... enfin s'exécutera toujours avant une instruction return, peu importe où ce retour est dans le corps de la méthode. Si ce n'était pas le cas, le bloc finalement n'aurait pas beaucoup de sens.


7

En plus du point sur le retour pour remplacer finalement un retour dans le bloc try, il en va de même pour une exception. Un bloc finally qui lève une exception remplacera un retour ou une exception levée depuis le bloc try.


7

finally va s'exécuter et c'est sûr.

finally ne s'exécutera pas dans les cas ci-dessous:

cas 1 :

Lorsque vous exécutez System.exit().

cas 2:

Lorsque votre JVM / Thread plante.

cas 3:

Lorsque votre exécution est arrêtée entre les deux manuellement.


6
  1. Enfin, Block est toujours exécuté. Sauf si et jusqu'à ce que l' instruction System.exit () existe (première instruction dans le bloc enfin).
  2. Si system.exit () est la première instruction, alors finalement le bloc ne sera pas exécuté et le contrôle sortira du bloc finalement. Chaque fois que l'instruction System.exit () pénètre enfin dans le bloc jusqu'à l'exécution définitive de cette instruction et lorsque System.exit () apparaît, la force de contrôle sort complètement du bloc finally.

1
Cela a été répondu plusieurs fois, alors quelles nouvelles informations votre réponse ajoute-t-elle?
Tom
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.