Sur une question pour Java à l'université, il y avait cet extrait de code:
class MyExc1 extends Exception {}
class MyExc2 extends Exception {}
class MyExc3 extends MyExc2 {}
public class C1 {
public static void main(String[] args) throws Exception {
try {
System.out.print(1);
q();
}
catch (Exception i) {
throw new MyExc2();
}
finally {
System.out.print(2);
throw new MyExc1();
}
}
static void q() throws Exception {
try {
throw new MyExc1();
}
catch (Exception y) {
}
finally {
System.out.print(3);
throw new Exception();
}
}
}
On m'a demandé de donner sa sortie. J'ai répondu 13Exception in thread main MyExc2
, mais la bonne réponse est 132Exception in thread main MyExc1
. Qu'est-ce que c'est? Je ne comprends tout simplement pas où MyExc2
va.
Voici ce que Wikipedia dit à propos de la clause finally:
Décortiquons votre programme.
Donc,
1
sera affiché à l'écran, puisq()
est appelé. Dansq()
, une exception est levée. L'exception est alors interceptéeException y
mais elle ne fait rien. Une clause finally est alors exécutée (c'est3
nécessaire ), donc, sera imprimée à l'écran. Parce que (dans la méthode,q()
il y a une exception levée dans la clause finally , laq()
méthode transmet également l'exception à la pile parent (par lathrows Exception
déclaration de méthode)new Exception()
sera levée et interceptée parcatch ( Exception i )
, l'MyExc2
exception sera levée (pour l'instant, ajoutez-la à la pile d'exceptions ), mais un enfin dans lemain
bloc sera exécuté en premier.Alors dedans,
Une clause finally est appelée ... (rappelez-vous, nous venons juste d'attraper
Exception i
et de jeterMyExc2
) essentiellement,2
est imprimée à l'écran ... et après l'2
impression de la à l'écran, uneMyExc1
exception est levée.MyExc1
est géré par lapublic static void main(...)
méthode.Production:
Le conférencier a raison! :-)
En substance , si vous avez un finally dans une clause try / catch, un finally sera exécuté ( après avoir intercepté l'exception avant de lever l'exception interceptée)
la source
catch
est exécuté depuisq()
jeté unException
de son proprefinally
bloc.q
passe l'exécution aucatch
bloc vide dansq
(qui avale cette exception), puis aufinally
bloc dansq
. Dit enfin le bloc imprime3
, puis lève une nouvelle exception, qui grâce àq
'sthrows Exception
est transmise à la pile au parent.Les exceptions dans le bloc finally remplacent les exceptions dans le bloc catch.
Citant l' édition 14 de la spécification du langage Java :
la source
Enfin, la clause est exécutée même lorsqu'une exception est lancée de n'importe où dans le bloc try / catch.
Parce que c'est le dernier à être exécuté dans le
main
et qu'il lève une exception, c'est l'exception que les appelants voient.D'où l'importance de s'assurer que la
finally
clause ne jette rien, car elle peut avaler des exceptions dutry
blocage.la source
A
method
ne peut pas fairethrow
deux exceptions en même temps. Il lancera toujours le dernier lancéexception
, qui dans ce cas sera toujours celui dufinally
bloc.Lorsque la première exception de la méthode
q()
est levée, elle sera interceptée puis avalée par l'exception finalement bloquée.q () -> jeté
new Exception
->main
catch Exception
->throw
new Exception
->finally
lancer un nouveauexception
(et celui de lacatch
est "perdu")la source
La manière la plus simple de penser à cela est d'imaginer qu'il existe une variable globale à l'ensemble de l'application qui contient l'exception actuelle.
Lorsque chaque exception est levée, "currentException" est défini sur cette exception. Lorsque l'application se termine, si currentException est! = Null, le moteur d'exécution signale l'erreur.
De plus, les blocs finally s'exécutent toujours avant la fin de la méthode. Vous pouvez ensuite demander à l'extrait de code:
L'ordre dans lequel l'application s'exécute est:
la source
Il est bien connu que le bloc finally est exécuté après le try and catch et qu'il est toujours exécuté ... ne faites pas toujours ce qu'ils devraient faire dans l'ordre que nous attendons du thème.
À votre santé.
la source
Ordre:
https://www.compilejava.net/
la source
La logique est claire jusqu'à la fin de l'impression
13
. Puis l'exception jetéq()
est pris parcatch (Exception i)
dansmain()
etnew MyEx2()
est prêt à être jeté. Cependant, avant de lever l'exception, lefinally
bloc doit d'abord être exécuté. Ensuite, la sortie devient132
etfinally
demande de lever une autre exceptionnew MyEx1()
.Comme une méthode ne peut pas en lancer plus d'un
Exception
, elle lancera toujours la dernièreException
. En d'autres termes, si les deux blocscatch
etfinally
essaient de lancerException
, alors laException
prise d' entrée est avalée et seule l'exception d'finally
entrée sera lancée.Ainsi, dans ce programme, Exception
MyEx2
est avalée etMyEx1
levée. Cette exception est levéemain()
et n'est plus interceptée, ainsi la JVM s'arrête et la sortie finale est132Exception in thread main MyExc1
.En substance, si vous avez une clause
finally
in atry/catch
, afinally
sera exécuté APRÈS avoir intercepté l'exception , mais AVANT de lancer une exception interceptée , et SEULE la dernière exception sera levée à la fin .la source
Je pense qu'il suffit de parcourir les
finally
blocs:finally
dans l'q
impression « 3 ».finally
enmain
caractères d'imprimerie "2".la source
Pour gérer ce genre de situation, c'est-à-dire gérer l'exception levée par le bloc finally. Vous pouvez entourer le bloc finally par try block: Regardez l'exemple ci-dessous en python:
la source
Je pense que cela résout le problème:
la source