O ile wiem, oba poniższe fragmenty kodu będą służyć temu samemu celowi. Dlaczego finally
w ogóle mają bloki?
Kod A:
try { /* Some code */ }
catch { /* Exception handling code */ }
finally { /* Cleanup code */ }
Kod B:
try { /* Some code */ }
catch { /* Exception handling code */ }
// Cleanup code
Odpowiedzi:
Throwable
...)finally
Blok zapewnia, że jednak po wyjściu tego bloku (modulo kilka sposobów przerywania cały proces wyraźnie), zostanie on wykonany. Jest to ważne dla deterministycznego oczyszczania zasobów.źródło
System.exit()
wywołanie (2) istnieje nieskończona pętla w try lub jednym z bloków catch (3)Zauważ, że (przynajmniej w Javie, prawdopodobnie także w C #) jest również możliwe, aby
try
blok był bez acatch
, ale z rozszerzeniemfinally
. Gdy wtry
bloku wystąpi wyjątek , kod wfinally
bloku jest uruchamiany, zanim wyjątek zostanie zgłoszony wyżej:InputStream in = new FileInputStream("somefile.xyz"); try { somethingThatMightThrowAnException(); } finally { // cleanup here in.close(); }
źródło
Możesz chcieć umieścić kod, który mimo wszystko ma zostać wykonany niezależnie od tego, co dzieje się w twoim bloku try lub catch.
Również jeśli używasz wielu catch i jeśli chcesz wstawić jakiś kod, który jest wspólny dla wszystkich bloków catch, będzie to miejsce do umieszczenia - ale nie możesz być pewien, że cały kod w try został wykonany.
Na przykład:
conn c1 = new connection(); try { c1.dosomething(); } catch (ExceptionA exa) { handleexA(); //c1.close(); } catch (ExceptionB exb) { handleexB(); //c1.close(); } finally { c1.close(); }
źródło
W końcu zawsze zostaje wykonany, podczas gdy twój kod po złapaniu może nie.
źródło
Mimo że nasza aplikacja jest zamykana na siłę, będą pewne zadania, które musimy wykonać (takie jak zwolnienie pamięci, zamknięcie bazy danych, blokada zwolnienia itp.), Jeśli napiszesz te wiersze kodu w
finally
bloku, zostanie ono wykonane niezależnie od tego, czy zostanie zgłoszony wyjątek nie...Twoja aplikacja może być zbiorem wątków,
Exception
kończy wątek, ale nie całą aplikację, w tym przypadkufinally
jest bardziej przydatna.W niektórych przypadkach
finally
nie można wykonać, na przykład błąd JVM, zakończenie wątku itp.źródło
Ponieważ potrzebujesz tego kodu do wykonania niezależnie od wyjątków, które mogą zostać wyrzucone. Na przykład może być konieczne wyczyszczenie jakiegoś niezarządzanego zasobu (konstrukcja „using” kompiluje się do bloku try / last).
źródło
Może się zdarzyć, że będziesz chciał wykonać fragment kodu bez względu na wszystko. Czy wyjątek został zgłoszony, czy nie. Następnie używa się
finally
.źródło
finally
ZAWSZE wykonuje, chyba że JVM została wyłączona,finally
po prostu zapewnia metodę umieszczenia kodu porządkującego w jednym miejscu.Byłoby zbyt uciążliwe, gdybyś musiał umieścić kod czyszczący w każdym z
catch
bloków.źródło
Jeśli blok catch zgłosi jakikolwiek wyjątek, pozostały kod nie zostanie wykonany, dlatego musimy napisać blok.
źródło
Wreszcie blok w javie może być użyty do umieszczenia "porządkującego" kodu, takiego jak zamknięcie pliku, zamknięcie połączenia itp.
Ostatni blok nie zostanie wykonany, jeśli program zakończy działanie (albo przez wywołanie System.exit (), albo przez spowodowanie błędu krytycznego, który spowoduje przerwanie procesu).
źródło
Wciąż przewijasz w dół? Proszę bardzo!
To pytanie dawało mi trudny czas.
try { int a=1; int b=0; int c=a/b; } catch(Exception ex) { console.writeline(ex.Message); } finally { console.writeline("Finally block"); } console.writeline("After finally");
co zostałoby wydrukowane w powyższym scenariuszu? Tak, zgadłem:
np. wiadomość - cokolwiek to jest (prawdopodobnie próba podzielenia przez zero)
Wreszcie blok
W końcu
try { int a=1; int b=0; int c=a/b; } catch(Exception ex) { throw(ex); } finally { console.writeline("Finally block"); } console.writeline("After finally");
Co by to wydrukowało? Nic! Zgłasza błąd, ponieważ blok catch wywołał błąd.
W dobrej strukturze programowania twoje wyjątki byłyby lejkami, w tym sensie, że ten kod będzie obsługiwany z innej warstwy. Aby stymulować taki przypadek, zagnieżdżę ten kod.
try { try { int a=1; int b=0; int c=a/b; } catch(Exception ex) { throw(ex); } finally { console.writeline("Finally block") } console.writeline("After finally"); } catch(Exception ex) { console.writeline(ex.Message); }
W tym przypadku wynik wyglądałby następująco:
Oczywiste jest, że gdy wychwycisz wyjątek i wrzucisz go ponownie do innych warstw (lejkowanie), kod po rzucie nie zostanie wykonany. Działa podobnie do tego, jak działa powrót wewnątrz funkcji.
Teraz wiesz, dlaczego nie zamknąć zasobów na kodach po bloku catch i umieścić je w bloku final.
źródło