Pertanyaan Apakah akhirnya selalu mengeksekusi di Jawa?


Mempertimbangkan kode ini, bisakah saya benar-benar yakin bahwa finally blokir selalu mengeksekusi, tidak peduli apa something() aku s?

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("i don't know if this will get printed out.");
}

1901
2017-09-15 17:43


asal


Jawaban:


Iya nih, finally akan dipanggil setelah pelaksanaan percobaan atau menangkap blok kode.

Satu-satunya waktu finally tidak akan dipanggil adalah:

  1. Jika Anda memohon System.exit();
  2. Jika JVM crash pertama;
  3. Jika JVM mencapai loop tak terbatas (atau beberapa pernyataan non-interruptable, non-terminating) di dalam try atau catch blok;
  4. Jika OS secara paksa mengakhiri proses JVM; misalnya "kill -9" pada UNIX.
  5. Jika sistem host mati; misalnya kegagalan daya, kesalahan perangkat keras, kepanikan OS, dan sebagainya.
  6. Jika akhirnya blokir akan dieksekusi oleh daemon thread dan semua thread non daemon lainnya keluar sebelum akhirnya dipanggil.

2114
2017-09-15 17:45



Kode contoh:

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int test() {
    try {
        return 0;
    }
    finally {
        System.out.println("finally trumps return.");
    }
}

Keluaran:

finally trumps return. 
0

444
2017-09-15 17:59



Juga, meskipun itu praktik yang buruk, jika ada pernyataan kembali dalam blok terakhir, itu akan mengalahkan pengembalian lainnya dari blok reguler. Artinya, blok berikut akan mengembalikan salah:

try { return true; } finally { return false; }

Hal yang sama dengan melemparkan pengecualian dari blok akhirnya.


323
2017-09-15 18:19



Inilah kata-kata resmi dari Spesifikasi Bahasa Jawa.

14.20.2. Eksekusi coba-coba dan coba-tangkap akhirnya

SEBUAH try pernyataan dengan finally blok dijalankan oleh pertama mengeksekusi try blok. Maka ada pilihan:

  • Jika eksekusi dari try blok selesai secara normal, [...]
  • Jika eksekusi dari try blok selesai tiba-tiba karena throw suatu nilai V, [...]
  • Jika eksekusi dari try blok selesai tiba-tiba karena alasan lain R, lalu finally blok dijalankan. Maka ada pilihan:
    • Jika akhirnya blok selesai secara normal, maka try Pernyataan selesai tiba-tiba karena alasan R.
    • Jika itu finally blok selesai tiba-tiba karena alasan S, lalu try Pernyataan selesai tiba-tiba karena alasan S (dan alasan R dibuang).

Spesifikasi untuk return sebenarnya membuat ini eksplisit:

JLS 14.17 Pernyataan kembali

ReturnStatement:
     return Expression(opt) ;

SEBUAH return pernyataan tanpa Expression  upaya untuk mentransfer kontrol ke penyiar metode atau konstruktor yang berisi itu.

SEBUAH return pernyataan dengan Expression  upaya untuk mentransfer kontrol ke penyiar metode yang berisi itu; nilai dari Expression menjadi nilai dari pemanggilan metode.

Deskripsi sebelumnya mengatakan "upaya untuk mentransfer kontrol"bukan hanya"transfer kontrol"karena jika ada try pernyataan dalam metode atau konstruktor yang try blok berisi return pernyataan, lalu apa saja finally klausa dari mereka try pernyataan akan dilaksanakan, dalam urutan, terdalam ke terluar, sebelum kontrol ditransfer ke penyiar metode atau konstruktor. Penyelesaian tiba-tiba a finally klausa dapat mengganggu transfer kontrol yang diprakarsai oleh return pernyataan.


229
2018-05-25 06:50



Selain tanggapan lainnya, penting untuk menunjukkan bahwa 'akhirnya' memiliki hak untuk mengganti pengecualian / nilai kembali apa pun oleh blok try..catch. Misalnya, kode berikut mengembalikan 12:

public static int getMonthsInYear() {
    try {
        return 10;
    }
    finally {
        return 12;
    }
}

Demikian pula, metode berikut ini tidak membuang pengecualian:

public static int getMonthsInYear() {
    try {
        throw new RuntimeException();
    }
    finally {
        return 12;
    }
}

Sementara metode berikut ini membuangnya:

public static int getMonthsInYear() {
    try {
        return 12;          
    }
    finally {
        throw new RuntimeException();
    }
}

134
2018-05-13 07:11



Saya mencoba contoh di atas dengan sedikit modifikasi-

public static void main(final String[] args) {
    System.out.println(test());
}

public static int test() {
    int i = 0;
    try {
        i = 2;
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
    }
}

Output kode di atas:

akhirnya mengalahkan kembali.
  2

Ini karena kapan return i; dieksekusi i memiliki nilai 2. Setelah ini finally blok dijalankan di mana 12 ditugaskan untuk i lalu System.out keluar dijalankan.

Setelah mengeksekusi finally memblokir try blok mengembalikan 2, daripada mengembalikan 12, karena pernyataan kembali ini tidak dieksekusi lagi.

Jika Anda akan mendebug kode ini di Eclipse maka Anda akan mendapat perasaan bahwa setelah mengeksekusi System.out dari finally memblokir return pernyataan dari try blok dijalankan lagi. Tetapi bukan ini masalahnya. Ini hanya mengembalikan nilai 2.


88
2017-11-17 16:25



Berikut ini penjelasan lebih lanjut Jawaban Kevin. Penting untuk mengetahui bahwa ekspresi yang akan dikembalikan dievaluasi sebelumnya finally, bahkan jika itu dikembalikan setelahnya.

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int printX() {
    System.out.println("X");
    return 0;
}

public static int test() {
    try {
        return printX();
    }
    finally {
        System.out.println("finally trumps return... sort of");
    }
}

Keluaran:

X
finally trumps return... sort of
0

80
2017-12-03 23:36



Itu adalah ide keseluruhan dari blok akhirnya. Ini memungkinkan Anda memastikan Anda melakukan pembersihan yang mungkin dilewati karena Anda kembali, di antara hal-hal lain, tentu saja.

Akhirnya dipanggil terlepas dari apa yang terjadi di blok coba (kecuali kalau kamu panggil System.exit(int) atau Java Virtual Machine dijalankan untuk alasan lain).


46
2018-05-13 06:19



Cara yang logis untuk memikirkan hal ini adalah:

  1. Kode ditempatkan di blok akhirnya harus dieksekusi apa pun yang terjadi dalam blok coba
  2. Jadi jika kode di blok coba mencoba mengembalikan nilai atau melempar pengecualian, item ditempatkan 'di rak' hingga blok terakhir dapat dijalankan
  3. Karena kode di blok terakhir memiliki (berdasarkan definisi) prioritas tinggi, ia dapat kembali atau membuang apa pun yang disukainya. Dalam hal apa yang tersisa 'di rak' dibuang.
  4. Satu-satunya pengecualian untuk ini adalah jika VM mati sepenuhnya selama blok coba, mis. oleh 'System.exit'

31
2017-09-15 19:26



Juga kembali pada akhirnya akan membuang pengecualian. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html


14
2017-09-15 19:26