Java Try Catch Akhirnya memblokir tanpa Catch


125

Saya meninjau beberapa kode baru. Program ini memiliki percobaan dan akhirnya hanya memblokir. Karena blok tangkap dikecualikan, bagaimana cara kerja blok coba jika menemukan pengecualian atau apa pun yang dapat dibuang? Apakah itu langsung menuju ke blok terakhir?



25
@mP Setiap orang harus melakukan review kode dan mengajukan pertanyaan dari mereka adalah bagaimana belajar dan meningkatkan.
Carl Pritchett

Jawaban:


130

Jika salah satu kode dalam blok percobaan dapat memunculkan pengecualian yang dicentang, kode itu harus muncul di klausa lemparan dari tanda tangan metode. Jika pengecualian yang tidak dicentang dilemparkan, itu menggelembung keluar dari metode.

Blok terakhir selalu dijalankan, baik pengecualian dilempar atau tidak.


11
Paragraf pertama belum tentu benar. Coba blok bisa bersarang. Pengecualian yang tidak tertangkap, tidak dicentang atau tidak, akan keluar dari metode ini.
Andy Thomas

4
Coba blok bisa bersarang, tapi saya tidak akan merekomendasikannya. Saya tidak menulis kode seperti itu.
duffymo

2
@ Duffymo: Apa yang dimaksud dengan "menggelegak keluar dari metode"?
Hari iniDipelajari

5
@Anand hanya beberapa bahasa yang sedikit non-teknis untuk "melempar pengecualian".
duffymo

2
Tidak diabaikan; melewatkan rantai metode.
duffymo

93

Catatan kecil di try/ finally: Akhirnya akan selalu dijalankan kecuali

  • System.exit() disebut.
  • JVM macet.
  • The try{}blok tidak pernah berakhir (misalnya tak berujung loop).

4
Tentang apa try{..} catch{ throw ..} finally{..}? Saya pikir akhirnya tidak akan dieksekusi
sbeliakov

10
Dalam hal itu akhirnya tetap akan dipanggil. Hanya pengecualian asli yang hilang.
Peter Lawrey

Akhirnya juga tidak akan dijalankan jika Anda memanggil System.exit () sebelumnya.
mmirror

2
@jyw Itulah yang saya maksud dengan item pertama dalam daftar di atas.
Peter Lawrey

Saya harus mengatakan, ini mencakup semua pangkalan!
Oscar Bravo

39

Spesifikasi Bahasa Java (1) menjelaskan bagaimana try-catch-finallydijalankan. Tidak memiliki tangkapan sama dengan tidak memiliki tangkapan yang mampu menangkap Throwable yang diberikan.

  • Jika eksekusi blok percobaan selesai secara tiba-tiba karena lemparan nilai V, maka ada pilihan:
    • Jika tipe run-time V dapat ditetapkan ke parameter klausa catch apa pun dari pernyataan coba, maka
      ……
    • Jika tipe run-time V tidak dapat ditetapkan ke parameter dari klausa catch dari pernyataan try, maka blok akhirnya dieksekusi . Lalu ada pilihan:
      • Jika blok akhirnya selesai secara normal, maka pernyataan try selesai secara tiba-tiba karena lemparan nilai V.
      • Jika blok akhirnya selesai secara tiba-tiba karena alasan S, maka pernyataan percobaan selesai secara tiba-tiba karena alasan S (dan lemparan nilai V dibuang dan dilupakan).

(1) Eksekusi coba-tangkap-akhirnya


16

Bagian dalam akhirnya dieksekusi sebelum melempar pengecualian ke blok luar.

public class TryCatchFinally {

  public static void main(String[] args) throws Exception {

    try{
        System.out.println('A');
        try{
            System.out.println('B');
            throw new Exception("threw exception in B");
        }
        finally
        {
            System.out.println('X');
        }
        //any code here in the first try block 
        //is unreachable if an exception occurs in the second try block
    }
    catch(Exception e)
    {
        System.out.println('Y');
    }
    finally
    {
        System.out.println('Z');
    }
  }
}

Hasil dalam

A
B
X
Y
Z

6

Blok terakhir selalu dijalankan setelah blok percobaan berakhir, apakah percobaan berakhir secara normal atau tidak normal karena pengecualian, er, dapat dibuang.

Jika pengecualian dilempar oleh salah satu kode dalam blok percobaan, maka metode saat ini hanya melempar kembali (atau terus melempar) pengecualian yang sama (setelah menjalankan blok akhirnya).

Jika blok terakhir melempar pengecualian / kesalahan / dapat dibuang, dan sudah ada lemparan tertunda, itu menjadi jelek. Sejujurnya, saya lupa persis apa yang terjadi (begitu banyak untuk sertifikasi saya bertahun-tahun yang lalu). Saya pikir kedua lemparan terhubung bersama, tetapi ada beberapa voodoo khusus yang harus Anda lakukan (yaitu - panggilan metode yang harus saya cari) untuk mendapatkan masalah asli sebelum "akhirnya" muntah, er, muntah.

Kebetulan, coba / akhirnya adalah hal yang cukup umum untuk dilakukan untuk manajemen sumber daya, karena java tidak memiliki destruktor.

Mis -

r = new LeakyThing();
try { useResource( r); }
finally { r.release(); }  // close, destroy, etc

"Akhirnya", satu tip lagi: jika Anda repot - repot memasukkan tangkapan, baik menangkap subkelas throwable spesifik (yang diharapkan), atau cukup menangkap "Throwable", bukan "Exception", untuk perangkap kesalahan umum semua. Terlalu banyak masalah, seperti kesalahan refleksi, melempar "Kesalahan", bukan "Pengecualian", dan masalah itu akan hilang dengan benar oleh "tangkap semua" yang dikodekan sebagai:

catch ( Exception e) ...  // doesn't really catch *all*, eh?

lakukan ini sebagai gantinya:

catch ( Throwable t) ...

Lihat jawaban oleh Carlos Heuberger di bawah untuk bagian yang jelek.
mplwork

3

Versi Java sebelum versi 7 memungkinkan tiga kombinasi coba-tangkap-akhirnya ...

try - catch
try - catch - finally
try - finally

finallyblok akan selalu dieksekusi apa pun yang terjadi di tryatau / dan catchblokir. jadi jika tidak ada catchblokir, pengecualian tidak akan ditangani di sini.

Namun, Anda masih memerlukan penangan pengecualian di suatu tempat dalam kode Anda - kecuali jika Anda ingin aplikasi Anda benar-benar mogok. Itu tergantung pada arsitektur aplikasi Anda persis di mana handler itu berada.

  • Blok percobaan Java harus diikuti oleh blok tangkapan atau blok terakhir.
  • Untuk setiap blok percobaan mungkin ada nol atau lebih blok tangkap, tetapi hanya satu blok akhirnya.
  • Blok terakhir tidak akan dijalankan jika program keluar (baik dengan memanggil System.exit () atau dengan menyebabkan kesalahan fatal yang menyebabkan proses dibatalkan).

1
"sebelum versi 7 diizinkan", apakah Anda menyiratkan bahwa Java 7 dan Java 8 tidak mengizinkan ketiga kombinasi ini? Saya ragu itu yang Anda maksud, tetapi itulah yang tersirat dari jawaban Anda.
Loduwijk

apakah blok terakhir dieksekusi jika ada pernyataan kembali di blok percobaan?
Rahul Yadav

@Rahul Ya, akhirnya akan dipanggil. Ref: stackoverflow.com/questions/65035/…
roottraveller

1
@Aaron - sintaks baru untuk try-with-resource yang secara otomatis memanggil .close () pada apa pun yang dibuat dalam tanda kurung tepat setelah kata kunci try.
Roboprog

2

bagaimana cara kerja blok percobaan jika menemukan pengecualian atau apa pun yang dapat dibuang

Pengecualian dilempar keluar dari blok, seperti dalam kasus lain di mana tidak tertangkap.

Blok terakhir dijalankan terlepas dari bagaimana blok percobaan keluar - terlepas dari apakah ada tangkapan sama sekali, terlepas dari apakah ada tangkapan yang cocok.

Blok tangkapan dan yang terakhir adalah bagian ortogonal dari blok uji coba. Anda dapat memiliki salah satu atau keduanya. Dengan Java 7, Anda tidak dapat memiliki keduanya!


1

Apakah Anda tidak mencobanya dengan program itu? Itu akhirnya akan memblokir dan mengeksekusi blok terakhir, tetapi, pengecualian tidak akan ditangani. Tapi, pengecualian itu bisa dibatalkan di blok terakhir!


1

Blok terakhir dijalankan setelah blok percobaan selesai. Jika sesuatu dilempar ke dalam blok percobaan ketika meninggalkan blok akhirnya dijalankan.


0

Di dalam tryblok kami menulis kode yang dapat memunculkan pengecualian. The catchblok di mana kami menangani pengecualian. The finallyblock selalu dieksekusi tidak peduli apakah pengecualian terjadi atau tidak.

Sekarang jika kita memiliki blok coba-akhirnya daripada blok coba-tangkap-akhirnya maka pengecualian tidak akan ditangani dan setelah blok coba alih-alih kontrol akan menangkap blok itu akan pergi ke blok akhirnya. Kita dapat menggunakan blok coba-akhirnya ketika kita tidak ingin melakukan apa pun dengan pengecualian.


0

Terlepas dari pengecualian dilempar atau tidak di tryblok - finallyblokir akan dieksekusi. Pengecualian tidak akan tertangkap.

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.