Sintaks coba-dengan-sumber daya Java 7 (juga dikenal sebagai blok ARM ( Manajemen Sumber Daya Otomatis )) bagus, pendek dan mudah ketika menggunakan hanya satu AutoCloseablesumber daya. Namun, saya tidak yakin apa idiom yang benar ketika saya perlu mendeklarasikan banyak sumber daya yang saling bergantung, misalnya a FileWriterdan a BufferedWriteryang membungkusnya. Tentu saja, pertanyaan ini menyangkut masalah ketika beberapa AutoCloseablesumber daya dibungkus, tidak hanya dua kelas khusus ini.
Saya datang dengan tiga alternatif berikut:
1)
Ungkapan naif yang saya lihat adalah mendeklarasikan hanya pembungkus tingkat atas dalam variabel yang dikelola ARM:
static void printToFile1(String text, File file) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
Ini bagus dan pendek, tetapi rusak. Karena yang mendasarinya FileWritertidak dideklarasikan dalam variabel, itu tidak akan pernah ditutup langsung di finallyblok yang dihasilkan . Itu akan ditutup hanya melalui closemetode pembungkus BufferedWriter. Masalahnya adalah, bahwa jika pengecualian dilemparkan dari bwkonstruktor, itu closetidak akan dipanggil dan karena itu yang mendasarinya FileWriter tidak akan ditutup .
2)
static void printToFile2(String text, File file) {
try (FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw)) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
Di sini, sumber daya pokok dan pembungkus dideklarasikan dalam variabel yang dikelola ARM, sehingga keduanya pasti akan ditutup, tetapi dasarnya fw.close() akan dipanggil dua kali : tidak hanya secara langsung, tetapi juga melalui pembungkus bw.close().
Ini seharusnya tidak menjadi masalah untuk dua kelas khusus ini yang keduanya mengimplementasikan Closeable(yang merupakan subtipe dari AutoCloseable), yang kontraknya menyatakan bahwa beberapa panggilan closediizinkan:
Menutup aliran ini dan melepaskan sumber daya sistem apa pun yang terkait dengannya. Jika aliran sudah ditutup maka menjalankan metode ini tidak akan berpengaruh.
Namun, dalam kasus umum, saya dapat memiliki sumber daya yang hanya menerapkan AutoCloseable(dan tidak Closeable), yang tidak menjamin yang closedapat dipanggil beberapa kali:
Perhatikan bahwa tidak seperti metode tutup java.io.Closeable, metode tutup ini tidak diperlukan untuk menjadi idempoten. Dengan kata lain, memanggil metode tutup ini lebih dari sekali mungkin memiliki beberapa efek samping yang terlihat, tidak seperti Closeable.close yang diperlukan untuk tidak memiliki efek jika dipanggil lebih dari sekali. Namun, pelaksana antarmuka ini sangat dianjurkan untuk membuat metode mereka dekat idempoten.
3)
static void printToFile3(String text, File file) {
try (FileWriter fw = new FileWriter(file)) {
BufferedWriter bw = new BufferedWriter(fw);
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
Versi ini harus benar secara teoritis, karena hanya fwmewakili sumber daya nyata yang perlu dibersihkan. Itu bwsendiri tidak memiliki sumber daya apa pun, itu hanya mendelegasikan ke fw, jadi itu harus cukup untuk hanya menutup yang mendasarinya fw.
Di sisi lain, sintaksnya agak tidak teratur dan juga, Eclipse mengeluarkan peringatan, yang saya percaya merupakan alarm palsu, tetapi itu masih merupakan peringatan bahwa seseorang harus berurusan dengan:
Kebocoran sumber daya: 'bw' tidak pernah ditutup
Jadi, pendekatan mana yang harus ditempuh? Atau apakah saya melewatkan beberapa idiom lain yang benar ?
public BufferedWriter(Writer out, int sz)bisa melempar IllegalArgumentException. Juga, saya dapat memperluas BufferedWriter dengan kelas yang akan membuang sesuatu dari konstruktornya atau membuat bungkus kustom apa pun yang saya butuhkan.
BufferedWriterkonstruktor dapat dengan mudah melempar pengecualian. OutOfMemoryErrormungkin yang paling umum karena mengalokasikan sebagian besar memori untuk buffer (walaupun mungkin mengindikasikan Anda ingin me-restart seluruh proses). / Anda perlu flushAnda BufferedWriterjika Anda tidak dekat dan ingin menyimpan isi (umumnya hanya kasus non-pengecualian). FileWritermengambil apa pun yang terjadi sebagai pengkodean file "default" - lebih baik untuk menjadi eksplisit.