Dlaczego używamy bloczków Final?

91

O ile wiem, oba poniższe fragmenty kodu będą służyć temu samemu celowi. Dlaczego finallyw 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
Mohammad Nadeem
źródło
To nie jest specyficzne dla C #, jest to pytanie .Net
Sruly
1
Nie jest już potrzebne z java7: AutomaticResourceManagement, wypróbuj (new resourceDeclartion ()) {}
Kanagavelu Sugumar

Odpowiedzi:

139
  • Co się stanie, jeśli wyjątek, którego nie obsługujesz, zostanie wyrzucony? (Mam nadzieję, że nie łapiesz Throwable...)
  • Co się stanie, jeśli wrócisz z wnętrza bloku try?
  • Co się stanie, jeśli blok catch zgłosi wyjątek?

finallyBlok 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.

Jon Skeet
źródło
48
Niekoniecznie prawda; w końcu nie zostanie wykonany, jeśli (1) jest System.exit()wywołanie (2) istnieje nieskończona pętla w try lub jednym z bloków catch (3)
Wyciągam
2
@Alon try {return 1; } wreszcie {retrun 2; } Otrzymasz 2
Dennis C
19
@NullUserException: Stąd bit „modulo na kilka sposobów ...”
Jon Skeet
2
John Skeet mieszka tutaj na stackoverflow, każde pytanie jest jak dzwonek do drzwi, na który musi odpowiedzieć :)
naikus
1
W tym poście omówiono (rzadkie) warunki, w których w końcu NIE zostanie wywołany.
Candamir
13

Zauważ, że (przynajmniej w Javie, prawdopodobnie także w C #) jest również możliwe, aby tryblok był bez a catch, ale z rozszerzeniem finally. Gdy w trybloku wystąpi wyjątek , kod w finallybloku jest uruchamiany, zanim wyjątek zostanie zgłoszony wyżej:

InputStream in = new FileInputStream("somefile.xyz");
try {
    somethingThatMightThrowAnException();
}
finally {
    // cleanup here
    in.close();
}
Jesper
źródło
7

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();
}
Balaji Natesan
źródło
1
Co się stanie, jeśli nie użyję „na koniec”, ale zamknę połączenie?
Istiaque Ahmed
5

W końcu zawsze zostaje wykonany, podczas gdy twój kod po złapaniu może nie.

Sruly
źródło
1
Dlaczego nie! Jeśli wyjątek jest obsługiwany prawidłowo, kod zostanie ostatecznie wykonany.
Mohammad Nadeem
1
@ Nadeem: Zobacz moją odpowiedź z 3 powodów, że może się nie zdarzyć.
Jon Skeet
2

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 finallybloku, zostanie ono wykonane niezależnie od tego, czy zostanie zgłoszony wyjątek nie...

Twoja aplikacja może być zbiorem wątków, Exceptionkończy wątek, ale nie całą aplikację, w tym przypadku finallyjest bardziej przydatna.

W niektórych przypadkach finallynie można wykonać, na przykład błąd JVM, zakończenie wątku itp.

Sandeep P.
źródło
1

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).

Ed S.
źródło
0

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.

Egalitarny
źródło
0

finallyZAWSZE wykonuje, chyba że JVM została wyłączona, finallypo 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 catchbloków.

Mahmoud Hanafy
źródło
0

Jeśli blok catch zgłosi jakikolwiek wyjątek, pozostały kod nie zostanie wykonany, dlatego musimy napisać blok.

Reshma Kore
źródło
0

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).

Aakersh Sharma
źródło
0

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:

  • Wreszcie blok
  • np. wiadomość - cokolwiek to jest.

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.

Ashique razak
źródło