Apakah blok akhirnya berjalan bahkan jika Anda membuang Pengecualian baru?

142

Dalam kode ini akan someVarditetapkan bahkan jika blok tangkapan dieksekusi dan Pengecualian kedua dilemparkan?

public void someFunction() throws Exception {
    try {
        //CODE HERE
    } catch (Exception e) {
        Log.e(TAG, "", e);
        throw new Exception(e);
    } finally {
        this.someVar= true;
    }
}
Jax
sumber
2
Karena ada keadaan di mana perilaku tidak seperti yang diharapkan, seperti ditunjukkan oleh @GaryF
jax
1
Perlu dicatat bahwa blok terakhir mungkin tidak dieksekusi seperti yang diharapkan jika melempar pengecualian, atau melakukan pengembalian.
Peter Lawrey

Jawaban:

184

Ya, blok terakhir selalu berjalan ... kecuali ketika:

  • Utas yang menjalankan blok coba-tangkap-akhirnya terbunuh atau terputus
  • Kau gunakan System.exit(0);
  • VM yang mendasarinya dihancurkan dengan cara lain
  • Perangkat keras yang mendasarinya tidak dapat digunakan dalam beberapa cara

Selain itu, jika suatu metode di blok Anda akhirnya melempar pengecualian yang tidak tertangkap, maka tidak ada setelah itu akan dieksekusi (yaitu pengecualian akan dilemparkan seperti halnya dalam kode lainnya). Kasus yang sangat umum dimana ini terjadi adalah java.sql.Connection.close().

Sebagai tambahan, saya menduga bahwa contoh kode yang Anda gunakan hanyalah sebuah contoh, tetapi hati-hati menempatkan logika aktual di dalam blok akhirnya. Blok akhirnya ditujukan untuk pembersihan sumber daya (menutup koneksi DB, melepaskan pegangan file dll), bukan untuk logika yang harus dijalankan. Jika harus dijalankan, lakukan sebelum blok coba-tangkap, jauh dari sesuatu yang bisa menimbulkan pengecualian, karena niat Anda hampir pasti sama secara fungsional.

GaryF
sumber
4
Apa yang Anda maksud di sini dengan "Utas yang menjalankan blok coba-tangkap-akhirnya [...] terganggu"? Mungkin dokumentasi itu tidak ditulis dengan baik, tetapi Thread.interrupt () tidak akan menyebabkan blok akhirnya dilewati, baik dilemparkan dari percobaan atau blok tangkapan. Apakah ini menggunakan "terputus" berarti sesuatu yang lebih keras, seperti Thread.stop ()?
Joe Kearney
@ Jo: Ya, saya pikir dokumentasinya sedikit buruk di sini, dan itu berarti gangguan umum pada aktivitas utas.
GaryF
@GaryF - Saya pikir Anda mengutip dari JLS. Kata-kata JLS kadang-kadang agak aneh, tetapi Anda biasanya akan menemukan bahwa makna terminologi aneh didefinisikan dengan jelas di tempat lain dalam dokumen. JLS adalah spesifikasi dan memiliki presisi (bukan keterbacaan) sebagai tujuan utamanya.
Stephen C
1
@Stephen C - Sebenarnya, itu berasal dari tutorial JavaSE (ditautkan oleh orang lain). Ini mungkin sama dengan kata-kata di JLS, tetapi saya tidak dapat menemukan bagian yang relevan. Saya mengharapkan ini dalam bab 11 (Pengecualian), bab 14 (Pernyataan) atau bab 15 (Ekspresi), tetapi tidak dapat melihat apa pun yang merujuk pada gangguan secara eksplisit. Saya pasti akan tertarik melihatnya.
GaryF
1
@GaryF - Begitu. Sebenarnya JLS berbicara tentang pemutusan pernyataan "normal" dan "mendadak", dan ada bagian (14.1) yang mendefinisikan terminologi. Perilaku finallyini kemudian ditentukan dalam hal penghentian normal dan tiba-tiba.
Stephen C
10

Iya.

Lihat dokumentasi :

Blok akhirnya selalu dijalankan ketika blok coba keluar.

Pengecualian:

Catatan: Jika JVM keluar saat kode coba atau tangkap dijalankan, maka blok akhirnya mungkin tidak dapat dijalankan. Demikian juga, jika utas yang mengeksekusi kode coba atau tangkap terganggu atau terbunuh, blok akhirnya mungkin tidak dapat dijalankan meskipun aplikasi secara keseluruhan berlanjut.

froadie
sumber
2

Akhirnya, blok selalu dijalankan.

public class ExceptionTest {

public static void someFunction(String input) throws Exception {
    try {
        if( input.equals("ABC") ) {
            System.out.println("Matched");
        }
    } catch (Exception e) {
        throw new Exception(e);
    } finally {
        System.out.println("Input Is "+input+" Finally Executed!!!");
    }
}

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    try {
        System.out.println("********* Test with VALUE ********* ");
        someFunction("ABC");
        System.out.println("\r\n********* Test with NULL  ********* ");
        someFunction(null);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}

Java Try Catch Akhirnya Blokir dengan Throw

Vasanth Umapathy
sumber
2

Akhirnya selalu dieksekusi, tidak peduli apa kasus Anda yaitu

  • blok coba-tangkap-akhirnya
  • melempar

Untuk pengecualian yang tidak dicentang, java tidak mengamanatkan, penanganan kesalahan. inilah alasannya, jika pengecualian yang tidak dicentang terjadi pada akhirnya blok dan tidak ada penanganan yang dilakukan untuk itu, maka kode yang ditulis di bawah titik ini (di mana kesalahan telah terjadi) tidak akan dieksekusi.

Jadi saya sarankan untuk selalu menangani semua pengecualian, apakah itu dapat diperiksa atau tidak dicentang. Dengan cara ini Anda dapat memastikan bahwa blok kode pada akhirnya juga dieksekusi tidak masalah jika pengecualian tidak dicentang juga terjadi. Anda memiliki tempat di tangkapan sub-sarang dan Akhirnya memblokir untuk menyelesaikan pekerjaan Anda.

Yug
sumber
1

Iya. finallyblok selalu dijalankan kecuali jika Anda memanggil System.exit () karena menghentikan Java VM.

Vladimir Ivanov
sumber
Shutdown hooks masih dipanggil setelah System.exit (), tetapi utas non-sistem yang ada semuanya dihentikan.
Peter Lawrey