Java 7 , kaynaklarla deneme sözdizimi (ARM bloğu ( Otomatik Kaynak Yönetimi ) olarak da bilinir ), yalnızca bir AutoCloseablekaynak kullanılırken güzel, kısa ve anlaşılır . Ancak, birbirine bağlı birden fazla kaynak, örneğin a FileWriterve BufferedWriteronu saran birden fazla kaynak bildirmek gerektiğinde doğru deyimin ne olduğundan emin değilim . Tabii ki, bu soru AutoCloseable, sadece bu iki özel sınıfla değil, bazı kaynakların sarıldığı herhangi bir durumla ilgilidir .
Aşağıdaki üç alternatif buldum:
1)
Gördüğüm naif deyim, sadece ARM tarafından yönetilen değişkende en üst düzey sarmalayıcıyı bildirmektir:
static void printToFile1(String text, File file) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
Bu güzel ve kısa, ama kırık. Temel alınan FileWriterbir değişkente bildirilmediğinden, hiçbir zaman doğrudan üretilen finallyblokta kapatılmaz . Sadece closesarma yöntemi ile kapatılacaktır BufferedWriter. Sorun şu ki, bwyapıcıdan bir istisna atılırsa, closeçağrılmayacak ve bu nedenle altta yatan FileWriter kapanmayacaktır .
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
}
}
Burada, hem temel hem de sarma kaynağı ARM tarafından yönetilen değişkenlerde bildirilir, bu nedenle her ikisi de kesinlikle kapatılacaktır, ancak altta yatan fw.close() iki kez çağrılacaktır : sadece doğrudan değil, aynı zamanda sarma yoluyla bw.close().
Bu, her ikisinin de uyguladığı Closeable(bir alt türü olan AutoCloseable) bu iki özel sınıf için, sorun birden fazla çağrıya closeizin verildiğini belirten bir sorun olmamalıdır :
Bu akışı kapatır ve onunla ilişkili tüm sistem kaynaklarını serbest bırakır. Akış zaten kapalıysa, bu yöntemin başlatılmasının bir etkisi yoktur.
Bununla birlikte, genel bir durumda, birden fazla kez çağrılabileceğini garanti etmeyen, sadece AutoCloseable(ve değil Closeable) uygulayan kaynaklara sahip closeolabilirim:
Java.io.Closeable kapat yönteminin aksine, bu kapat yönteminin idempotent olması gerekmez. Başka bir deyişle, bu kapat yöntemini bir kereden fazla çağırmak, birden fazla çağrılırsa hiçbir etkisi olmaması gereken Closeable.close öğesinin aksine bazı görünür yan etkilere sahip olabilir. Bununla birlikte, bu arayüzün uygulayıcılarının yakın yöntemlerini idempotent yapmaları şiddetle tavsiye edilir.
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
}
}
Bu sürüm teorik olarak doğru olmalıdır, çünkü sadece fwtemizlenmesi gereken gerçek bir kaynağı temsil eder. bwİçin, sadece delegeler herhangi bir kaynak tutamaz kendisi vermez fwsadece yakın yatan için yeterli olmalıdır, böylece fw.
Öte yandan, sözdizimi biraz düzensizdir ve ayrıca, Eclipse yanlış bir alarm olduğuna inandığım bir uyarı yayınlar, ancak yine de ilgilenilmesi gereken bir uyarıdır:
Kaynak sızıntısı: 'bw' asla kapatılmaz
Peki, hangi yaklaşımı benimsemek? Yoksa doğru olan başka bir deyimi kaçırdım mı?
public BufferedWriter(Writer out, int sz)bir IllegalArgumentException. Ayrıca, BufferedWriter'ı yapıcısından bir şey atacak veya ihtiyacım olan herhangi bir özel sarmalayıcı oluşturacak bir sınıfla genişletebilirim.
BufferedWriterYapıcı kolayca istisna atabilir. OutOfMemoryErrorarabellek için adil bir bellek ayırdığı için en yaygın olanıdır (ancak tüm işlemi yeniden başlatmak istediğinizi gösterebilir). / Sen gerek flushSİZİN BufferedWriterdeğil yakın yapmak ve içerikleri (genellikle tutmak istiyorsanız sadece sigara istisna durum). FileWriter"varsayılan" dosya kodlaması ne olursa olsun alır - açık olması daha iyidir.