Java Try Catch Finalnie blokuje bez Catch


125

Sprawdzam nowy kod. Program ma tylko próbę i ostatecznie blokuje. Ponieważ blok catch jest wykluczony, w jaki sposób działa blok try, jeśli napotka wyjątek lub cokolwiek, co można wyrzucić? Czy po prostu przechodzi bezpośrednio do ostatniego bloku?



25
@mP Każdy powinien przeglądać kod i zadawać pytania, jak się uczyć i doskonalić.
Carl Pritchett

Odpowiedzi:


130

Jeśli jakikolwiek kod w bloku try może zgłosić sprawdzony wyjątek, musi pojawić się w klauzuli throws podpisu metody. Jeśli zostanie zgłoszony niesprawdzony wyjątek, zostanie on przepuszczony z metody.

Ostatni blok jest zawsze wykonywany, niezależnie od tego, czy został zgłoszony wyjątek, czy nie.


11
Pierwszy akapit niekoniecznie jest prawdziwy. Bloki prób mogą być zagnieżdżane. Każdy niewyłapany wyjątek, niezaznaczony lub nie, wypłynie z metody.
Andy Thomas

4
Bloki prób mogą być zagnieżdżane, ale nie polecam tego. Nie piszę kodu w ten sposób.
duffymo

2
@duffymo: Co to znaczy „wypłynął z metody”?
Dzisiaj Nauczyłem się

5
@An i tylko trochę nietechniczny język do „zgłaszania wyjątków”.
duffymo

2
Nie ignorowane; przekazać łańcuch metod.
duffymo

93

Mała uwaga na temat try/ finally: Final zawsze będzie wykonywany, chyba że

  • System.exit() jest nazywany.
  • JVM ulega awarii.
  • W try{}bloku nigdy końców (na przykład pętla bez końca).

4
O co chodzi try{..} catch{ throw ..} finally{..}? Myślę, że ostatecznie nie zostanie stracony
sbeliakov

10
W takim przypadku ostatecznie nadal będzie wywoływany. Tylko oryginalny wyjątek zostanie utracony.
Peter Lawrey,

Ostatecznie również nie zostanie wykonane, jeśli wcześniej wywołasz System.exit ().
mmirror

2
@jyw To właśnie miałem na myśli, mówiąc o pierwszej pozycji z powyższej listy.
Peter Lawrey

Muszę powiedzieć, że obejmuje to wszystkie podstawy!
Oscar Bravo

39

Specyfikacja języka Java (1) opisuje sposób try-catch-finallywykonywania. Brak zaczepu jest równoznaczny z brakiem możliwości złapania danego Rzutu.

  • Jeśli wykonanie bloku try kończy się nagle z powodu rzutu o wartości V, wówczas istnieje wybór:
    • Jeśli typ czasu wykonywania V można przypisać do parametru dowolnej klauzuli catch instrukcji try, to
      ……
    • Jeśli typu V w czasie wykonywania nie można przypisać do parametru żadnej klauzuli catch instrukcji try, wykonywany jest ostatni blok . Następnie jest wybór:
      • Jeśli ostatni blok kończy się normalnie, instrukcja try kończy się nagle z powodu rzutu o wartości V.
      • Jeśli ostatni blok kończy się nagle z powodu S, to instrukcja try kończy się nagle z powodu S (a rzut wartości V jest odrzucany i zapomniany).

(1) Wykonanie try-catch-last


16

Ostatecznie wewnętrzny jest wykonywany przed wyrzuceniem wyjątku do zewnętrznego bloku.

public class TryCatchFinally {

  public static void main(String[] args) throws Exception {

    try{
        System.out.println('A');
        try{
            System.out.println('B');
            throw new Exception("threw exception in B");
        }
        finally
        {
            System.out.println('X');
        }
        //any code here in the first try block 
        //is unreachable if an exception occurs in the second try block
    }
    catch(Exception e)
    {
        System.out.println('Y');
    }
    finally
    {
        System.out.println('Z');
    }
  }
}

Prowadzi do

A
B
X
Y
Z

6

Ostatni blok jest zawsze uruchamiany po zakończeniu bloku try, niezależnie od tego, czy try kończy się normalnie, czy nienormalnie z powodu wyjątku, eee, rzucanego.

Jeśli wyjątek zostanie zgłoszony przez dowolny kod w bloku try, wówczas bieżąca metoda po prostu ponownie zgłasza (lub nadal zgłasza) ten sam wyjątek (po uruchomieniu ostatniego bloku).

Jeśli ostatni blok rzuca wyjątek / błąd / rzucanie, a istnieje już oczekujący przedmiot do rzucania, robi się brzydki. Szczerze mówiąc, dokładnie zapominam, co się dzieje (tyle z mojego certyfikatu sprzed lat). Myślę, że oba przedmioty miotane łączą się ze sobą, ale jest pewne specjalne voodoo, które musisz zrobić (tj. Wywołanie metody, którą musiałbym podnieść), aby rozwiązać pierwotny problem, zanim „w końcu” zwymiotował, eee, zwymiotował.

Nawiasem mówiąc, spróbuj / w końcu jest dość powszechną czynnością przy zarządzaniu zasobami, ponieważ java nie ma destruktorów.

Np. -

r = new LeakyThing();
try { useResource( r); }
finally { r.release(); }  // close, destroy, etc

„W końcu”, jeszcze jedna wskazówka: jeśli nie przeszkadza, aby umieścić w połowu, albo specyficzne catch (spodziewane) Throwable podklasy lub po prostu złapać „Throwable”, nie „Wyjątek” dla ogólnego catch-all pułapkę błędu. Zbyt wiele problemów, takich jak błędy związane z odbiciami, powoduje wyświetlenie „błędów” zamiast „wyjątków”, a te znikną po każdym „złapaniu wszystkiego” zakodowanym jako:

catch ( Exception e) ...  // doesn't really catch *all*, eh?

zrób to zamiast tego:

catch ( Throwable t) ...

Zobacz odpowiedź Carlosa Heubergera poniżej dla brzydkiej części.
mplwork,

3

Wersje Java przed wersją 7 pozwalają na te trzy kombinacje try-catch-last ...

try - catch
try - catch - finally
try - finally

finallyblok będzie zawsze wykonywany bez względu na to, co się dzieje w bloku trylub / i catch. więc jeśli nie ma catchbloku, wyjątek nie będzie tutaj obsługiwany.

Jednak nadal będziesz potrzebować obsługi wyjątków gdzieś w kodzie - chyba że chcesz, aby aplikacja całkowicie się zawiesiła. Zależy to od architektury aplikacji, w której dokładnie znajduje się ten program obsługi.

  • Po bloku try Java musi następować blok catch lub last block.
  • Dla każdego bloku try może być zero lub więcej bloków catch, ale tylko jeden blok końcowy.
  • Ostatni blok nie zostanie wykonany, jeśli program zakończy pracę (albo przez wywołanie System.exit (), albo przez wywołanie krytycznego błędu, który spowoduje przerwanie procesu).

1
„przed wersją 7 zezwalają” czy sugerujesz, że Java 7 i Java 8 nie zezwalają na te trzy kombinacje? Wątpię, że to masz na myśli, ale właśnie to sugeruje twoja odpowiedź.
Loduwijk

czy ostatni blok jest wykonywany, jeśli w bloku try znajduje się instrukcja return?
Rahul Yadav

@Rahul Tak, w końcu zostanie wywołany. Ref: stackoverflow.com/questions/65035/…
roottraveller

1
@Aaron - nowa składnia try-with-resource, która automagicznie wywołuje .close () na wszystkim, co zostało zbudowane w parens tuż po słowie kluczowym try.
Roboprog

2

jak działa blok try, jeśli napotka wyjątek lub cokolwiek, co można wyrzucić

Wyjątek jest wyrzucany z bloku, tak jak w każdym innym przypadku, gdy nie jest przechwytywany.

Ostateczny blok jest wykonywany niezależnie od tego, w jaki sposób blok try został zakończony - niezależnie od tego, czy w ogóle są jakieś catch, niezależnie od tego, czy istnieje pasujący catch.

Bloki catch i ostatnie są prostopadłymi częściami bloku try. Możesz mieć jedno lub oba. Z Javą 7 nie będziesz mieć żadnego!


1

Nie próbujesz tego z tym programem? W końcu zostanie zablokowany i wykonany zostanie ostatni blok, ale wyjątek nie zostanie obsłużony. Ale ten wyjątek można zmienić w ostatnim bloku!


1

Ostatni blok jest wykonywany po zakończeniu bloku try. Jeśli coś zostanie wrzucone do bloku try po opuszczeniu bloku, wykonywany jest ostatni blok.


0

Wewnątrz trybloku piszemy kody, które mogą zgłosić wyjątek. W catchbloku obsługujemy wyjątek. finallyBlok jest zawsze wykonywany bez względu na to, czy wyjątek występuje, czy nie.

Teraz, jeśli mamy blok try-final zamiast try-catch-last blok, wtedy wyjątek nie będzie obsługiwany i po bloku try zamiast kontroli będzie przechodził do bloku końcowego. Możemy użyć bloku try-final, gdy nie chcemy nic robić z wyjątkiem.


0

Niezależnie od wyjątku zgłoszonego lub nie w trybloku - finallyblok zostanie wykonany. Wyjątek nie zostałby przechwycony.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.