Java 7 , kaynaklarla deneme sözdizimi (ARM bloğu ( Otomatik Kaynak Yönetimi ) olarak da bilinir ), yalnızca bir AutoCloseable
kaynak kullanılırken güzel, kısa ve anlaşılır . Ancak, birbirine bağlı birden fazla kaynak, örneğin a FileWriter
ve BufferedWriter
onu 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 FileWriter
bir değişkente bildirilmediğinden, hiçbir zaman doğrudan üretilen finally
blokta kapatılmaz . Sadece close
sarma yöntemi ile kapatılacaktır BufferedWriter
. Sorun şu ki, bw
yapı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 close
izin 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 close
olabilirim:
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 fw
temizlenmesi gereken gerçek bir kaynağı temsil eder. bw
İçin, sadece delegeler herhangi bir kaynak tutamaz kendisi vermez fw
sadece 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.
BufferedWriter
Yapıcı kolayca istisna atabilir. OutOfMemoryError
arabellek 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 flush
SİZİN BufferedWriter
değ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.