Cześć!
Wraz z dzisiejszym wpisem chciałbym kontynuować serię o słowach kluczowych w języku Java. Jeśli przegapiłeś poprzedni wpis o słowie kluczowym “final“, to kliknij tutaj, aby przeczytać post. Pozwolę zacytować zdanie z poprzedniego wpisu: słowa kluczowe to jedno z częstych pytań na java junior developerów. Pytanie brzmi zazwyczaj: “wymień różnicę między „final”, „finally” oraz „finalize” wraz z przykładami praktycznymi”. W dzisiejszym wpisie na czynniki pierwsze rozłożymy słowo “finally” – do dzieła!
Finally
Przykład praktyczny

W powyzszym przykładzie, niezależnie od wartości parametru “length“, wirtualna maszyna javy wykona blok finally i wypisze “jestem w środku słowa kluczowego”.
Przykład użycia bez bloku catch

Wynikiem tej operacji będzie:

Dlaczego finally jest przydatne?
Zwykle bloku finally używa się do wykonywania kodu “czyszczącego”, tzn. do zamykania połączeń, plików czy zarządzania cyklem wątków, ponieważ jest wykona się zawsze, niezależnie od zachowania wyjątku.
Kiedy finally jest wykonywane?
Chciałbym omówić kilka przykładów wywołania bloku finally i wyjaśnić dlaczego wirtualna maszyna javy wywołuje kod w takiej, a nie innej kolejności.
Brak rzuconego wyjątku
Gdy blok try zakończy się, wykonywany jest blok finally, nawet jeśli wystąpił wyjątek:

W tym przykładzie, nie rzucamy wyjątku w bloku try. Z tego powodu wirtualna maszyna javy wykonuje cały kod zarówno w bloku try jak i finally. Wynik wykonywanego kodu będzie następujący:

Wyjątek jest rzucony lecz nieobsługiwany

JVM wykonuje blok finally nawet w przypadku nieobsłużonego wyjątku. Wyjście:

Wyjątek jest rzucony oraz obsłużony
Jeśli wystąpi wyjątek i zostanie on złapany przez blok catch, blok finally jest nadal wykonywany:

W tym przypadku, blok catch obsługuje rzucony wyjątek, a następnie JVM wykonuje blok finally i wypisuje następujące dane wyjściowe:

Return w bloku try
Return również nie zapobiegnie uruchomieniu bloku finally:

Kiedy rzucamy wyjątkiem z bloku try, blok catch odpowiednio się nim zajmie. Mimo, że w bloku catch znajduje się instrukcja return, JVM wykona blok finally przed przekazaniem kontroli do metody wywołującej. Dane wyjściowe będą następujące:

Return w bloku catch

Kiedy rzucamy wyjątek z bloku try, blok catch zajmuje się tym wyjątkiem. Mimo, że w bloku catch znajduje się instrukcja return, JVM wykonuje blok finally przed przekazaniem kontroli do metody wywołującej i wypisuje następujące dane:

No dobra, to kiedy finally się nie wykona?
Jak to w życiu bywa, zawsze znajdzie się wyjątek od reguły. Istnieją pewne sytuacje, kiedy JVM nie wykona bloku finally. Oto przykłady:
- System.exit(1) – w momencie, kiedy wywołamy System.exit(1) wykonywanie jakiegokolwiek dalszego kodu jest przerywane, co równoznaczne jest z zignorowaniem bloku finally
- Halt – podobnie jak w System.exit, wywołanie Runtime.halt również zatrzymuje wykonanie, a wirtualna maszyna javy nie wykona bloku finally
Podsumowanie
Pozdrawiam serdecznie,
biegajacyprogramista.pl