Sekiranya Kita Menutup Aliran Java?

1. Gambaran keseluruhan

Dengan pengenalan ungkapan lambda di Java 8, dapat menulis kod dengan cara yang lebih ringkas dan berfungsi. Stream dan Interface Fungsional adalah nadi perubahan revolusioner ini di platform Java.

Dalam tutorial ringkas ini, kita akan mengetahui sama ada kita harus menutup aliran Java 8 secara eksplisit dengan melihatnya dari perspektif sumber.

2. Menutup Aliran

Aliran Java 8 melaksanakan antara muka AutoCloseable :

public interface Stream extends BaseStream { // omitted } public interface BaseStream extends AutoCloseable { // omitted }

Sederhananya, kita harus menganggap aliran sebagai sumber yang boleh kita pinjam dan pulangkan apabila kita selesai dengannya. Berbanding dengan kebanyakan sumber, kita tidak perlu selalu menutup aliran.

Ini mungkin terdengar tidak intuitif pada mulanya, jadi mari kita lihat kapan kita harus dan kapan kita tidak boleh menutup aliran Java 8.

2.1. Koleksi, Susunan, dan Penjana

Selalunya, kami membuat contoh Aliran dari koleksi, susunan, atau fungsi penjana Java. Sebagai contoh, di sini, kami beroperasi pada koleksi String melalui Stream API:

List colors = List.of("Red", "Blue", "Green") .stream() .filter(c -> c.length() > 4) .map(String::toUpperCase) .collect(Collectors.toList());

Kadang kala, kami menghasilkan aliran berurutan yang terhad atau tidak terhingga:

Random random = new Random(); random.ints().takeWhile(i -> i < 1000).forEach(System.out::println);

Selain itu, kami juga dapat menggunakan aliran berdasarkan array:

String[] colors = {"Red", "Blue", "Green"}; Arrays.stream(colors).map(String::toUpperCase).toArray()

Semasa menangani aliran seperti ini, kita tidak boleh menutupnya secara eksplisit. Satu-satunya sumber berharga yang berkaitan dengan aliran ini adalah memori, dan Pengumpulan Sampah (GC) mengurusnya secara automatik.

2.2. Sumber IO

Sebilangan aliran, bagaimanapun, disokong oleh sumber IO seperti fail atau soket. Sebagai contoh, kaedah Files.lines () mengalirkan semua baris untuk fail yang diberikan:

Files.lines(Paths.get("/path/to/file")) .flatMap(line -> Arrays.stream(line.split(","))) // omitted

Di bawah tudung, kaedah ini membuka contoh FileChannel dan kemudian menutupnya semasa penutupan aliran. Oleh itu, jika kita lupa untuk menutup aliran, saluran yang mendasari akan tetap terbuka dan kemudian kita akan mengalami kebocoran sumber .

Untuk mengelakkan kebocoran sumber tersebut, sangat disarankan untuk menggunakan simpulan bahasa dengan sumber untuk menutup aliran berasaskan IO:

try (Stream lines = Files.lines(Paths.get("/path/to/file"))) { lines.flatMap(line -> Arrays.stream(line.split(","))) // omitted }

Dengan cara ini, penyusun akan menutup saluran secara automatik. Pengambilan kunci di sini adalah untuk menutup semua aliran berasaskan IO .

Harap maklum bahawa menutup aliran yang sudah ditutup akan membuang IllegalStateException .

3. Kesimpulannya

Dalam tutorial ringkas ini, kami melihat perbezaan antara aliran sederhana dan aliran berat IO. Kami juga mengetahui bagaimana perbezaan tersebut memberitahu keputusan kami mengenai menutup atau tidaknya aliran Java 8.

Seperti biasa, kod sampel boleh didapati di GitHub.