Exception throwed in catch and finally clause

W pytaniu o Javę na uniwersytecie, był taki fragment kodu:

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();
        }
    }
}
Poproszono mnie o podanie jej wyników. Odpowiedziałem 13Exception in thread main MyExc2, ale prawidłowa odpowiedź to 132Exception in thread main MyExc1. Dlaczego? Po prostu nie mogę zrozumieć, dokąd zmierza MyExc2.
Author: Nathan, 2010-09-23

10 answers

Patrząc na Twoją odpowiedź i widząc, jak prawdopodobnie ją wymyśliłeś, wierzę, że uważasz, że "wyjątek w toku" ma "pierwszeństwo". Pamiętaj:

Gdy nowy wyjątek zostanie wrzucony do bloku catch lub wreszcie bloku, który będzie propagował się poza tym blokiem, wtedy bieżący wyjątek zostanie przerwany (i zapomniany), gdy nowy wyjątek zostanie propagowany Na Zewnątrz. Nowy wyjątek rozpoczyna odwijanie stosu, tak jak każdy inny wyjątek, przerywając bieżący blok (połów lub wreszcie blok) i podlega wszelkim obowiązującym połowom lub wreszcie blokom po drodze.

Zauważ, że odpowiedni catch lub ostatecznie blocks zawiera:

Gdy nowy wyjątek zostanie wrzucony do bloku połowu, nowy wyjątek nadal będzie podlegał blokowi finally połowu, jeśli taki istnieje.

Teraz prześledzić wykonanie pamiętając, że za każdym razem, gdy naciśniesz throw, powinieneś przerwać śledzenie bieżącego wyjątku i rozpocząć śledzenie nowego wyjątek.

 127
Author: Bert F,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-10 13:33:13

Tak mówi Wikipedia o końcu klauzuli:

Bardziej powszechne jest klauzula związana (na koniec, lub zapewnić), że jest wykonywana czy wystąpił wyjątek, czy nie, zazwyczaj do uwolnienia zasobów nabyte w ciele blok obsługi wyjątków.

Przeanalizujmy Twój program.
try {
    System.out.print(1);
    q();
}

Tak więc, 1 Zostanie wyświetlone na ekranie, a następnie wywołane zostanie q(). W q() wyrzucany jest wyjątek. Wyjątek zostaje wówczas złapany przez Ale to nic nie robi. W końcu klauzula jest następnie wykonywana (musi), więc 3 zostanie wydrukowana na ekranie. Ponieważ (w metodzie q() jest wyjątek rzucony w W końcu klauzula, również q() metoda przekazuje wyjątek do stosu nadrzędnego (przez throws Exception w deklaracji metody) new Exception() zostanie rzucona i przechwycona przez catch ( Exception i ), MyExc2 wyjątek zostanie wyrzucony (na razie dodaj go do stosu wyjątków), ale W końcu w bloku main zostanie wykonany najpierw.

Więc w,

catch ( Exception i ) {
    throw( new MyExc2() );
} 
finally {
    System.out.print(2);
    throw( new MyExc1() );
}

A W końcu nazywa się klauzulę...(pamiętaj, że właśnie złapaliśmy Exception i i rzuciliśmy MyExc2) w istocie, 2 jest wydrukowany na ekranie...po wydrukowaniu 2 na ekranie wyświetlany jest wyjątek MyExc1. MyExc1 jest obsługiwane metodą public static void main(...).

Wyjście:

"132Exception w wątku głównym MyExc1"

Wykładowca ma rację! :-)

w istocie , jeśli masz W końcu w w tym celu należy wykonać polecenie try/catch (try / catch clause), a finally will be executed (after catching the exception before throwing the caught exception out)

 34
Author: Buhake Sindi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-19 11:14:13

Cytowanie z JLS 9: 14.20.2. Wykonanie try-finally I try-catch-finally

Jeśli blok catch zakończy się nagle z powodu R, to w końcu blok jest wykonywany. Wtedy jest wybór:

  • Jeśli blok finally zakończy się normalnie, Instrukcja TRY zakończy się nagle z powodu r.

  • Jeśli blok finally zakończy się nagle z powodu s, to polecenie TRY zakończy się nagle z powodu S (I powodu R jest odrzucony).

 26
Author: Roland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-16 10:42:22

Klauzula Finally jest wykonywana nawet wtedy, gdy wyjątek jest wyrzucany z dowolnego miejsca w bloku try/catch.

Ponieważ jest ostatnim wykonywanym w {[0] } i rzuca wyjątek, jest to wyjątek, który wywołujący widzą.

Stąd ważne jest upewnienie się, że klauzula finally niczego nie rzuca, ponieważ może połykać wyjątki z bloku try.

 18
Author: Alexander Pogrebnyak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-23 14:18:38

A method nie może throw dwóch WYJĄTKÓW w tym samym czasie. Zawsze rzuci ostatnią exception, która w tym przypadku będzie zawsze tą z finally bloku.

Kiedy pierwszy wyjątek z metody q() zostanie wyrzucony, zostanie złapany, a następnie połknięty przez ostatecznie wyrzucony wyjątek bloku.

Q() -> rzucone new Exception -> main catch Exception -> throw new Exception -> finally rzuć nowy exception (a ten z catch jest "zagubiony")

 7
Author: Garis M Suero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-23 14:31:26

Najprostszym sposobem na to jest wyobrażenie sobie, że istnieje zmienna global dla całej aplikacji, która przechowuje bieżący wyjątek.

Exception currentException = null;

Gdy każdy wyjątek jest wyrzucany," currentException " jest ustawiany na ten wyjątek. Po zakończeniu aplikacji, jeśli currentException jest != null, wtedy runtime zgłosi błąd.

Ponadto, bloki finally zawsze uruchamiane przed zakończeniem metody. Następnie możesz zażądać fragmentu kodu:

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
        }
    }
}

Kolejność, w jakiej wykonanie aplikacji to:

main()
{
  try
    q()
    {
      try
      catch
      finally
    }
  catch
  finally
}
 2
Author: CodingWithSpike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-23 14:28:57

Wiadomo, że blok finalny jest wykonywany po próbie i łapaniu i jest zawsze wykonywany.... Ale jak zauważyłeś, jest to trochę trudne czasami sprawdź te fragmenty kodu poniżej i będziesz to instrukcje return I throw nie zawsze robią to, co powinny zrobić w kolejności, jakiej oczekujemy od tematu.

Zdrówko.
/////////////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!";

}
////////////////////////////////////////////////// 
 1
Author: Sly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-19 11:14:52

Myślę, że wystarczy przejść finally klocki:

  1. Print "1".
  2. finally in q print "3".
  3. finally in main print "2".
 0
Author: Uwe Keim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-23 14:18:20
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();
    }
}

Kolejność:

TryA L1
TryA L2
Catch L2
Finally L2
Catch L1
Finally L1        
Exception in thread "main" MyExc1 at C1.main(C1.java:30)

Https://www.compilejava.net/

 0
Author: Luiz Fernando,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-27 11:49:55

Myślę, że to rozwiąże problem:

boolean allOk = false;
try{
  q();
  allOk = true;
} finally {
  try {
     is.close();
  } catch (Exception e) {
     if(allOk) {
       throw new SomeException(e);
     }
  }
}
 -1
Author: Vouze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-30 15:41:41