24

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

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

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

ответ

31

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

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

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 делает), или должны быть объявлены до ресурсов примерочных с-, то подходящее место для их закрытия находится в блоке finally, также упомянутом в связанной документации.

12

Не волнуйтесь, все будет «просто работать». От Socket's documentation:

Закрытие этого разъема также закроет 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() были сделаны идемпотентными).