Подтвердить что ты не робот

Закройте несколько ресурсов с помощью AutoCloseable (try-with-resources)

Я знаю, что ресурс, который вы передаете с попыткой, будет автоматически закрыт, если ресурс реализован AutoCloseable. Все идет нормально. Но что мне делать, когда у меня есть несколько ресурсов, которые я хочу автоматически закрыть. Пример с сокетами;

try (Socket socket = new Socket()) {
    input = new DataInputStream(socket.getInputStream());
    output = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
} 

Итак, я знаю, что сокет будет закрыт должным образом, потому что он передан как параметр в try, но как правильно закрыть вход и выход?

4b9b3361

Ответ 1

Попробуйте использовать ресурсы с несколькими ресурсами, объявив их все в скобках. См. Документацию

Соответствующий отрывок кода из связанной документации:

public static void writeToFileZipFileContents(String zipFileName,
                                           String outputFileName)
                                           throws java.io.IOException {

    java.nio.charset.Charset charset =
         java.nio.charset.StandardCharsets.US_ASCII;
    java.nio.file.Path outputFilePath =
         java.nio.file.Paths.get(outputFileName);

    // Open zip file and create output file with 
    // try-with-resources statement

    try (
        java.util.zip.ZipFile zf =
             new java.util.zip.ZipFile(zipFileName);
        java.io.BufferedWriter writer = 
            java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
    ) {
        // Enumerate each entry
        for (java.util.Enumeration entries =
                                zf.entries();     entries.hasMoreElements();) {
            // Get the entry name and write it to the output file
            String newLine = System.getProperty("line.separator");
            String zipEntryName =
                 ((java.util.zip.ZipEntry)entries.nextElement()).getName() 
             newLine;
            writer.write(zipEntryName, 0, zipEntryName.length());
        }
    }
}

Если ваши объекты не реализуют AutoClosable (DataInputStream), или должны быть объявлены перед try-with-ресурсами, то подходящее место для их закрытия находится в блоке finally, также упомянутом в связанная документация.

Ответ 2

Не волнуйтесь, все будет "просто работать". Из Документация к сокету:

Закрытие этого сокета также закроет сокет InputStream и OutputStream.

Я понимаю вашу озабоченность по поводу того, что я явно не вызываю close() на входные и выходные объекты, и на самом деле, как правило, лучше гарантировать, что все ресурсы автоматически управляются блоком try-with-resources, например:

try (Socket socket = new Socket();
     InputStream input = new DataInputStream(socket.getInputStream());
     OutputStream output = new DataOutputStream(socket.getOutputStream());) {
} catch (IOException e) {
} 

Это привело бы к тому, что объект сокета будет "закрыт несколько раз", но это не должно навредить (это одна из причин, почему обычно рекомендуется, чтобы все реализации close() были сделаны идемпотентными).