当前位置: 首页 > 知识库问答 >
问题:

使用AutoCloseable关闭多个资源(尝试使用资源)

吴高畅
2023-03-14

我知道,如果资源已实现自动关闭,您通过尝试传递的资源将自动关闭。到现在为止,一直都还不错。但是,当我有几个我想要自动关闭的资源时,我该怎么办呢。带插座的示例;

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

所以我知道套接字将被正确关闭,因为它在try中作为参数传递,但是输入和输出应该如何正确关闭呢?

共有3个答案

陶山
2023-03-14

除了上述答案,这是Java9中增加的改进。

Java 9 try with resources是一种改进的代码编写方式。现在,您可以在try块外部声明变量,并直接在try块内部使用它们。因此,您将获得以下好处。

  • 它在try之外声明的Resources(实际上是最终的或最终的)可以通过自动资源管理自动关闭,只需将它们添加到try块中。
    • 您不需要重新引用在try块之外声明的对象,也不需要手动关闭它们,因为我们需要在Java7中这样做。
    • 它也有助于编写干净的代码。

    在Java9中,我们可以这样写吗?

    public void loadDataFromDB() throws SQLException {
    Connection dbCon = DriverManager.getConnection("url", "user", "password");
    try (dbCon; ResultSet rs = dbCon.createStatement().executeQuery("select * from emp")) {
        while (rs.next()) {
            System.out.println("In loadDataFromDB() =====>>>>>>>>>>>> " + rs.getString(1));
        }
    } catch (SQLException e) {
        System.out.println("Exception occurs while reading the data from DB ->" + e.getMessage());
    }
    

    }

    在这里,自动资源管理将自动关闭两个对象dbCon

    为了更好地理解上述定义用例列表,请查找一些Java 7代码。

    例1:

    public void loadDataFromDB() throws SQLException {
    Connection dbCon = DriverManager.getConnection("url", "user", "password");
    try (ResultSet rs = dbCon.createStatement().executeQuery("select * from emp")) {
        while (rs.next()) {
            System.out.println("In loadDataFromDB() =====>>>>>>>>>>>> " + rs.getString(1));
        }
    } catch (SQLException e) {
        System.out.println("Exception occurs while reading the data from DB ->" + e.getMessage());
    } finally {
        if (null != dbCon)
            dbCon.close();
    }
    

    }

    例2:

    // BufferedReader is declared outside try() block
        BufferedReader br = new BufferedReader(new FileReader("C://readfile/input.txt"));
    
        try (BufferedReader inBr = br) {
                // ...
            }
        } catch (IOException e) {
            // ...
        }
    

    在上面的示例中,您可以看到对象是否是外部尝试,然后我们需要手动关闭或重新引用它。此外,在try块中有多个对象的情况下,它看起来很混乱,即使您在try内部声明,也不能使用外面的try块。

邬阳
2023-03-14

别担心,一切都会“顺利”的。从Socket的文档中:

关闭此套接字还将关闭套接字的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()的实现都被设为幂等的原因之一)。

太叔鸿
2023-03-14

Try with resources可以与多个资源一起使用,方法是在括号中声明所有资源。请参阅文档

链接文档中的相关代码摘录:

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());
        }
    }
}

如果您的对象没有实现AutoClosableDataInputStream实现),或者必须在使用资源进行尝试之前声明,那么关闭它们的适当位置是在链接文档中提到的finally块中。

 类似资料:
  • 不管错误情况如何,使用资源尝试是否总是关闭资源?我的意思是考虑以下代码: 会一直关闭吗?我读过Oracle文档,其中说: 无论try语句是正常完成还是突然完成,它都将关闭 因此无论程序正常运行还是抛出异常,它都将起作用。但是,类似或崩溃的情况怎么办?我知道这些条件对块不起作用。那么,使用资源尝试失败的条件是否存在? 这只是我请求的好奇心,谁能说明这一点吗?

  • try-with 功能如何适用于已声明为 变量? 我假设这会导致空指针异常,当它尝试调用上的变量,但它运行没有问题:

  • 问题内容: 我是的新手,我想知道对于资源来说,我是否必须为每个添加一个,否则它将与上面的代码一起使用 问题答案: 通过在 块中声明所有资源,可以尝试将资源与多个资源一起使用,并且此功能是 Java 7中 引入的,而不是 Java 8中 引入的。如果有多个资源,则可以如下所示 在此示例中,该语句包含两个用分号分隔的声明: ZipFile 和 BufferedWriter 。当它紧随其后的代码块终止时

  • 我是新手,我想知道,对于资源,我是否必须为每个

  • 根据Oracle文档 try with resources语句是声明一个或多个资源的try语句。资源是一个对象,在程序完成后必须关闭它。try with resources语句确保在语句末尾关闭每个资源。任何实现java的对象。AutoCloseable,其中包括实现java的所有对象。伊奥。可关闭,可用作资源 如果资源未实现AutoCloseable,则无法在try块中声明,必须在主体部分中声明

  • 我正在为面向对象编程的秋季考试做准备,其中一种任务是提供代码输出,这通常包括一些异常处理问题。 现在我的问题是什么时候用资源尝试关闭它的资源,因为我的输出严格依赖于实现AutoCloseable的类的输出。 在提供的代码中,我不明白为什么“close 1”输出在“close 40”之前,或者为什么对象A(40)在这个块的末尾被关闭。是因为A(50)和A(40)是同一类型的吗? 我的主要问题是,Au