Mengapa kami menggunakan blok terakhir?


91

Sejauh yang saya tahu, kedua potongan kode berikut akan melayani tujuan yang sama. Mengapa harus ada finallyblok?

Kode A:

try { /* Some code */ }
catch { /* Exception handling code */ }
finally { /* Cleanup code */ }

Kode B:

try { /* Some code */ }
catch { /* Exception handling code */ }
// Cleanup code

Ini tidak spesifik untuk C # ini adalah pertanyaan .Net
Sruly

1
Tidak diperlukan lagi dengan java7: AutomaticResourceManagement, coba (resourceDeclartion baru ()) {}
Kanagavelu Sugumar

Jawaban:


139
  • Apa yang terjadi jika pengecualian yang tidak Anda tangani dilemparkan? (Saya harap Anda tidak menangkap Throwable...)
  • Apa yang terjadi jika Anda kembali dari dalam blok percobaan?
  • Apa yang terjadi jika blok catch melontarkan pengecualian?

Sebuah finallyblok memastikan bahwa bagaimanapun Anda keluar dari blok itu (modulo beberapa cara untuk membatalkan seluruh proses secara eksplisit), itu akan dieksekusi. Itu penting untuk pembersihan sumber daya secara deterministik.


48
Belum tentu benar; akhirnya tidak akan dieksekusi jika (1) ada System.exit()panggilan (2) ada loop tak terbatas dalam percobaan atau salah satu blok tangkap (3) Saya mencabut steker di komputer
NullUserException

2
@Alon coba {return 1; } akhirnya {retrun 2; } Anda akan mendapatkan 2
Dennis C

19
@NullUserException: Oleh karena itu bit "modulo beberapa cara ..."
Jon Skeet

2
John Skeet tinggal di sini di stackoverflow, setiap pertanyaan seperti bel pintu yang harus dia jawab :)
naikus

1
Posting ini membahas kondisi (jarang) di mana akhirnya TIDAK AKAN dipanggil.
Candamir

13

Perhatikan bahwa (setidaknya di Java, mungkin juga di C #) juga memungkinkan untuk memiliki tryblok tanpa catch, tetapi dengan a finally. Ketika pengecualian terjadi di tryblok, kode di finallyblok dijalankan sebelum pengecualian dilemparkan lebih tinggi:

InputStream in = new FileInputStream("somefile.xyz");
try {
    somethingThatMightThrowAnException();
}
finally {
    // cleanup here
    in.close();
}

7

Anda mungkin ingin meletakkan kode yang Anda inginkan agar tetap dieksekusi terlepas dari apa yang terjadi di blok coba atau tangkap Anda.

Juga jika Anda menggunakan banyak tangkapan dan jika Anda ingin meletakkan beberapa kode yang umum untuk semua blok tangkapan ini akan menjadi tempat untuk meletakkan - tetapi Anda tidak dapat memastikan bahwa seluruh kode yang dicoba telah dieksekusi.

Sebagai contoh:

conn c1 = new connection();
try {
    c1.dosomething();
} catch (ExceptionA exa) {
    handleexA();
    //c1.close();
} catch (ExceptionB exb) {
    handleexB();
    //c1.close();
} finally {
    c1.close();
}

1
Bagaimana jika saya tidak menggunakan 'akhirnya' tetapi menutup koneksi?
Istiaque Ahmed

5

Akhirnya selalu dieksekusi, sedangkan kode Anda setelah tangkapan mungkin tidak.


1
kenapa tidak! Jika pengecualian ditangani dengan benar, kode akan dieksekusi dengan pasti.
Mohammad Nadeem

1
@Nadeem: Lihat jawaban saya untuk 3 alasan itu mungkin tidak terjadi.
Jon Skeet

2

Meskipun aplikasi kita ditutup secara paksa akan ada beberapa tugas, yang harus kita jalankan (seperti pelepasan memori, menutup database, kunci rilis, dll), jika Anda menulis baris kode ini di finallyblok, itu akan dijalankan apakah pengecualian dilemparkan atau tidak...

Aplikasi Anda mungkin kumpulan utas, Exceptionmengakhiri utas tetapi tidak seluruh aplikasi, dalam hal finallyini lebih berguna.

Dalam beberapa kasus finallytidak dapat dijalankan seperti JVM Fail, Thread terminate, dll.


1

Karena Anda memerlukan kode itu untuk dieksekusi terlepas dari pengecualian apa pun yang mungkin dilemparkan. Misalnya, Anda mungkin perlu membersihkan beberapa sumber daya yang tidak terkelola (konstruksi 'using' mengkompilasi ke blok coba / akhirnya).


0

Mungkin ada saatnya Anda ingin mengeksekusi sepotong kode apa pun yang terjadi. Apakah pengecualian dilempar atau tidak. Kemudian seseorang menggunakan finally.


0

finallySELALU dijalankan, kecuali JVM dimatikan, finallyhanya menyediakan metode untuk meletakkan kode pembersihan di satu tempat.

Akan sangat membosankan jika Anda harus meletakkan kode pembersihan di setiap catchblok.


0

Jika blok tangkap mengeluarkan pengecualian apa pun maka kode yang tersisa tidak akan dieksekusi sehingga kita harus menulis blok terakhir.


0

Akhirnya blok di java dapat digunakan untuk meletakkan kode "pembersihan" seperti menutup file, menutup koneksi dll.


Blok terakhir tidak akan dijalankan jika program keluar (baik dengan memanggil System.exit () atau dengan menyebabkan kesalahan fatal yang menyebabkan proses dibatalkan).


0

Masih menggulir ke bawah? Ini dia!

Pertanyaan ini memberi saya waktu yang sulit beberapa saat.

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");

apa yang akan dicetak dalam skenario di atas? Ya, tebak dengan benar:

  • mis. Pesan - apa pun itu (mungkin mencoba membagi dengan nol)

  • Terakhir blok

  • Setelah akhirnya

    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");
    

Apa yang akan dicetak ini? Tidak ada! Itu melempar kesalahan karena blok tangkap memunculkan kesalahan.

Dalam struktur pemrograman yang baik, pengecualian Anda akan disalurkan, dalam artian kode ini akan ditangani dari lapisan lain. Untuk merangsang kasus seperti itu saya akan mencoba kode ini bersarang.

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

Dalam hal ini, hasilnya adalah:

  • Terakhir blok
  • ex.Message - apapun itu.

Jelas bahwa ketika Anda menangkap pengecualian dan melemparkannya lagi ke lapisan lain (Funneling), kode setelah lemparan tidak dijalankan. Kerjanya mirip dengan bagaimana pengembalian di dalam suatu fungsi bekerja.

Anda sekarang tahu mengapa tidak menutup sumber daya Anda pada kode setelah blok catch. Tempatkan mereka di blok terakhir.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.