Java 8 Stream örnekleri her zaman yakın olmalı () 'd?


12

Quoth Javadoc :

Akışların BaseStream.close () yöntemi vardır ve AutoCloseable uygular, ancak neredeyse tüm akış örneklerinin kullanımdan sonra kapatılması gerekmez. Genel olarak, yalnızca kaynağı bir G / Ç kanalı olan akışların (Files.lines (Yol, Karakter Kümesi) tarafından döndürülenler gibi) kapatılması gerekir. Çoğu akış, özel kaynak yönetimi gerektirmeyen koleksiyonlar, diziler veya oluşturma işlevleri ile desteklenir. (Bir akış kapanmayı gerektiriyorsa, kaynaklarla dene ifadesinde kaynak olarak bildirilebilir.)

"Hemen hemen hepsi" ve "genellikle" belirsizdir - bir kitaplık yazıyorsanız ve Akışınızın kaynağını bu Akış'ın kullanıcılarından soyutluyorsanız, her zaman her zaman kendinize şu soruyu sormanız gerekir - "kapatmalı mıyım?" bu?" IO destekli Akışların kapatılması gerekiyor, çünkü terminal işlemleri çağrılamıyor close, bu yüzden etkin bir şekilde Akışımın nereden geldiğini hatırlamam / belgelemem gerekiyor veya her zaman buna ihtiyacım closevar.

Sanırım nükleer seçenek, Akışları yöntemlerden döndürmemek veya JDK ekibindeki bazı insanlar tarafından yankılanan bir duygu olan Akış parametrelerini kabul etmemektir. Akarsuların pratik yararları göz önüne alındığında bunu aşırı derecede sınırlayıcı buluyorum.

Akışları kapatma konusunda en iyi uygulamalarınız nelerdir? Çevrimiçi olarak, benzer topluluk soruları üzerinde aktif olan, ancak ilgili hiçbir şey bulamayan bazı JDK milletlerinden buna bir cevap aradım.


Bir Java geliştiricisi değil, ancak bu kuralları kullanırdım: - Bir akış bağımsız değişken olarak iletilirse, gerekirse arayanın akışı kapatması gerektiğini belgeleyin; - Akış size bir işlevden dönerse, kapatmanız gerektiğini varsayın.
Bart van Ingen Schenau

Yanıtlar:


6

Söylediğiniz gibi, Java'da tam olarak hangi kaynağı serbest bırakmaktan kimin sorumlu olduğunu bilmeniz gerekir, böylece uygun try-catch-builds, kaynaklarla deneme veya bir şekilde bu görevi devredebilirsiniz.

Sizin için temizlemek için GC'ye güvenebileceğiniz tek şey% 100 saf bellektir.
Orada ise belki karışık bazı diğer kaynakları olun, makul yapabileceğiniz tek şey sadece güvenli oynuyor.


Temel closeolarak tek güvenli alternatif mi? Herhalde soru bir Stream kullanımı kullanışlı olurdu her zaman aşırı çirkin görünmesini kod yapmak değil olduğunu.
RuslanD

1
Orada Evet, belki olmayan bellek kaynaklarını olmak, yapılacak tek güvenli şeydir orada farz olan . Java, GC'd olmayan kaynaklar için çok uygun olmamasına rağmen, bunun hiçbir yolu yoktur.
Tekilleştirici

Eğer bu sadece iki koleksiyon arasındaki bir akışsa (saf bellek), kapatmak gerekmez mi?
Amalgovinus

@Amalgovinus doğru
Brad Cupit

5

"En iyi uygulamalar" söz konusu olduğunda, "kaynak akışları" döndüren yöntemler için bir adlandırma kuralı kullanmak iyi bir fikir olduğunu düşünüyorum.

Bir akışın close()düzenlenmesi gerekiyorsa, fabrika yöntemini open()veya openStream(). stream()SDK tarafından kurulan sözleşmeyi takiben geçici akışlar oluşturan yöntemler çağırın . İstemciyi olması gerektiği konusunda uyarmak için daima javadoc yöntemine koyun close().

public interface StreamingServer<RECORD> {
    /** 
     * Return a memory-efficient record stream from {@code source}.
     * Clients <em>must</em> call {@link Stream#close} to dispose the
     * stream.
     */
    Stream<RECORD> openStream(URI source) throws IOException;
}

Keşke SDK yazarları AutoCloseabletemel akım sınıfını seçmemiş olsalardı. ResourceStreamÖnemsiz bir şekilde uygulanan farklı bir alt tip, AutoCloseablefarklı sözleşmeleri açıklığa kavuşturacaktı . O zaman Streamihtiyacı olmayan bir şeyi kapatamazsınız ve ResourceStreamstatik analiz araçlarında yanlış yönetilen potansiyelleri tespit edebilirsiniz .

Kod tabanınızın gereksinimlerine (ve kod incelemesinde kuralları uygulama yeteneğinize) bağlı olarak, kendiniz için yakın gerekli bir akış alt sınıfı oluşturabilirsiniz. Veya kendi statik analiz araçlarınızı oluşturmak istiyorsanız, yönetilen kaynakları doğrudan işaretleyen bir yöntem açıklaması.

@RequiresClose
Stream<RECORD> openStream(URI source) throws IOException { ... }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.