Op een vraag voor Java op de universiteit stond dit codefragment:
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();
}
}
}
Ik werd gevraagd om de output te geven. Ik heb 13Exception in thread main MyExc2
beantwoord, maar het juiste antwoord is 132Exception in thread main MyExc1
. Waarom is dat? Ik begrijp gewoon niet waar MyExc2
naartoe gaat.
Antwoord 1, autoriteit 100%
Op basis van het lezen van uw antwoord en het zien van hoe u het waarschijnlijk hebt bedacht, denk ik dat u denkt dat een “uitzondering in uitvoering” “voorrang” heeft. Onthoud:
Als een nieuwe uitzondering wordt gegooid in een catch-blok of uiteindelijk blokdat zich uit dat blok zal voortplanten, wordt de huidige uitzondering afgebroken (en vergeten) aangezien de nieuwe uitzondering is naar buiten gepropageerd. De nieuwe uitzondering begint de stapel af te wikkelen, net als elke andere uitzondering, waarbij het huidige blok wordt afgebroken (de vangst of uiteindelijk blok) en onderhevig aan eventuele toepasselijke vangsten of uiteindelijk blokkades.
Houd er rekening mee dat toepasselijke vangst of definitieve blokkadeshet volgende omvatten:
Als er een nieuwe uitzondering in een catch-blok wordt gegooid, is de nieuwe uitzondering nog steeds onderhevig aan de uiteindelijke blokkering van die vangst, indien van toepassing.
Herhaal nu de uitvoering en onthoud dat, wanneer u op throw
drukt, u het traceren van de huidige uitzondering moet afbreken en moet beginnen met het traceren van de nieuwe uitzondering.
Antwoord 2, autoriteit 28%
Uitzonderingen in het definitieve blok vervangen uitzonderingen in het catch-blok.
Als het catch-blok abrupt wordt voltooid om reden R, dan is de final
blok wordt uitgevoerd. Dan is er een keuze:
Als het final-blok normaal wordt voltooid, wordt het try-statement abrupt voltooid om reden R.
Als het blok final abrupt eindigt om reden S, dan wordt het try-statement abrupt voltooid om reden S (en reden R wordt weggegooid).
Antwoord 3, autoriteit 22%
Dit is wat Wikipediazegt over de definitieve clausule:
Meer gebruikelijk is een verwante clausule
(eindelijk, of ervoor zorgen) dat wordt uitgevoerd
of er een uitzondering is opgetreden of niet,
meestal om middelen vrij te geven
verworven in het lichaam van de
blokkering voor het afhandelen van uitzonderingen.
Laten we uw programma ontleden.
try {
System.out.print(1);
q();
}
Dus, 1
wordt op het scherm weergegeven, waarna q()
wordt aangeroepen. In q()
wordt een uitzondering gegenereerd. De uitzondering wordt dan opgevangen door Exception y
maar doet niets. Een finallyclausule wordt dan uitgevoerd (het moet), dus 3
wordt op het scherm afgedrukt. Omdat (in methode q()
er een uitzondering wordt gegenereerd in de finallyclausule, geeft ook de q()
methode de uitzondering door aan de bovenliggende stapel ( door de throws Exception
in de methodedeclaratie) new Exception()
wordt gegooid en opgevangen door catch ( Exception i )
, MyExc2
-uitzondering gegenereerd (voeg deze voorlopig toe aan de uitzonderingsstapel), maar een eindelijkin het main
-blok wordt eerst uitgevoerd.
Zo binnen,
catch ( Exception i ) {
throw( new MyExc2() );
}
finally {
System.out.print(2);
throw( new MyExc1() );
}
Een finallyclausule heet…(vergeet niet, we hebben zojuist Exception i
opgevangen en MyExc2
gegooid) in wezen, 2
wordt op het scherm afgedrukt…en nadat de 2
op het scherm is afgedrukt, wordt een MyExc1
-uitzondering gegenereerd. MyExc1
wordt afgehandeld door de methode public static void main(...)
.
Uitvoer:
“132Uitzondering in hoofdthread MyExc1”
Docent heeft gelijk! 🙂
In wezen, als je een finallyin een try/catch-clausule hebt, zal er een final worden uitgevoerd (nahet vangen van de uitzondering voordatde betrapte uitzondering weggooit)
Antwoord 4, autoriteit 12%
Ten slotte wordt de clausule uitgevoerd, zelfs als er een uitzondering wordt gegenereerd vanaf een willekeurige plek in het try/catch-blok.
Omdat het de laatste is die wordt uitgevoerd in de main
en het een uitzondering genereert, is dat de uitzondering die de bellers zien.
Vandaar het belang om ervoor te zorgen dat de finally
-clausule niets genereert, omdat het uitzonderingen van het try
-blok kan slikken.
Antwoord 5, autoriteit 5%
Een method
kan niet throw
twee uitzonderingen tegelijk. Het zal altijd de laatst gegenereerde Exception
genereren, wat in dit geval altijd het blok is van het finally
-blok.
Als de eerste uitzondering van de methode q()
wordt gegenereerd, wordt deze gevangen en vervolgens opgeslokt door de laatste uitzondering die wordt gegenereerd door blokkering.
q() ->gegooid new Exception
->main
catch Exception
->throw
new Exception
->finally
gooi een nieuwe Exception
(en die uit de catch
is “verloren”)
Antwoord 6, autoriteit 2%
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("TryA L1\n");
q();
System.out.print("TryB L1\n");
}
catch (Exception i) {
System.out.print("Catch L1\n");
}
finally {
System.out.print("Finally L1\n");
throw new MyExc1();
}
}
static void q() throws Exception {
try {
System.out.print("TryA L2\n");
q2();
System.out.print("TryB L2\n");
}
catch (Exception y) {
System.out.print("Catch L2\n");
throw new MyExc2();
}
finally {
System.out.print("Finally L2\n");
throw new Exception();
}
}
static void q2() throws Exception {
throw new MyExc1();
}
}
Bestelling:
TryA L1
TryA L2
Catch L2
Finally L2
Catch L1
Finally L1
Exception in thread "main" MyExc1 at C1.main(C1.java:30)
Antwoord 7, autoriteit 2%
De gemakkelijkste manier om hieraan te denken is door je voor te stellen dat er een globale variabele is voor de hele applicatie die de huidige uitzondering bevat.
Exception currentException = null;
Als elke uitzondering wordt gegenereerd, wordt “currentException” op die uitzondering ingesteld. Wanneer de toepassing eindigt, als currentException != null is, rapporteert de runtime de fout.
Ook worden de blokken tenslotte altijd uitgevoerd voordat de methode wordt afgesloten. U kunt het codefragment dan opnieuw vragen aan:
public class C1 {
public static void main(String [] argv) throws Exception {
try {
System.out.print(1);
q();
}
catch ( Exception i ) {
// <-- currentException = Exception, as thrown by q()'s finally block
throw( new MyExc2() ); // <-- currentException = MyExc2
}
finally {
// <-- currentException = MyExc2, thrown from main()'s catch block
System.out.print(2);
throw( new MyExc1() ); // <-- currentException = MyExc1
}
} // <-- At application exit, currentException = MyExc1, from main()'s finally block. Java now dumps that to the console.
static void q() throws Exception {
try {
throw( new MyExc1() ); // <-- currentException = MyExc1
}
catch( Exception y ) {
// <-- currentException = null, because the exception is caught and not rethrown
}
finally {
System.out.print(3);
throw( new Exception() ); // <-- currentException = Exception
}
}
}
De volgorde waarin de toepassing wordt uitgevoerd is:
main()
{
try
q()
{
try
catch
finally
}
catch
finally
}
Antwoord 8
De logica is duidelijk totdat het afdrukken van 13
is voltooid. Vervolgens wordt de uitzondering die in q()
wordt gegenereerd, opgevangen door catch (Exception i)
in main()
en een new MyEx2()
is klaar om te worden gegooid. Voordat de uitzondering wordt gegenereerd, moet echter eerst het blok finally
worden uitgevoerd. Dan wordt de uitvoer 132
en finally
vraagt ​​om nog een uitzondering new MyEx1()
te genereren.
Omdat een methode niet meer dan één Exception
kan genereren, zal deze altijd de laatste Exception
genereren. Met andere woorden, als zowel catch
als finally
blokken proberen om Exception
te gooien, dan is de Exception
in catch geslikten alleen de uitzondering in finally
wordt gegenereerd.
Dus in dit programma wordt Uitzondering MyEx2
ingeslikt en MyEx1
wordt gegenereerd. Deze uitzondering wordt uit main()
gegooid en niet langer gevangen, dus JVM stopt en de uiteindelijke uitvoer is 132Exception in thread main MyExc1
.
In wezen, als je een finally
in een try/catch
-clausule hebt, wordt een finally
uitgevoerd NA het vangen van de uitzondering, maar VOORDAT er een betrapte uitzondering wordt gegooid, en ALLEEN de laatste uitzondering wordt uiteindelijk gegooid.
Antwoord 9
Het is algemeen bekend dat het final-blok wordt uitgevoerd na de try and catch en altijd wordt uitgevoerd….
Maar zoals je hebt gezien, is het soms een beetje lastig, kijk eens naar dat codefragment hieronder en je zult dat doen
de return- en throw-statements doen niet altijd wat ze zouden moeten doen in de volgorde die we van het thema verwachten.
Proost.
/////////////Return dont always return///////
try{
return "In Try";
}
finally{
return "In Finally";
}
////////////////////////////////////////////
////////////////////////////////////////////
while(true) {
try {
return "In try";
}
finally{
break;
}
}
return "Out of try";
///////////////////////////////////////////
///////////////////////////////////////////////////
while (true) {
try {
return "In try";
}
finally {
continue;
}
}
//////////////////////////////////////////////////
/////////////////Throw dont always throw/////////
try {
throw new RuntimeException();
}
finally {
return "Ouuuups no throw!";
}
//////////////////////////////////////////////////
Antwoord 10
Ik denk dat je gewoon de finally
blokken moet lopen:
- Druk “1” af.
finally
inq
druk “3” af.finally
inmain
print “2”.
Antwoord 11
Om dit soort situaties aan te pakken, d.w.z. het afhandelen van de uitzondering die is gegenereerd door eindelijk blokkeren. Je kunt het laatste blok omringen met een try-blok: kijk naar het onderstaande voorbeeld in python:
try:
fh = open("testfile", "w")
try:
fh.write("This is my test file for exception handling!!")
finally:
print "Going to close the file"
fh.close()
except IOError:
print "Error: can\'t find file or read data"
Antwoord 12
Ik denk dat dit het probleem oplost:
boolean allOk = false;
try{
q();
allOk = true;
} finally {
try {
is.close();
} catch (Exception e) {
if(allOk) {
throw new SomeException(e);
}
}
}