Java7 try-with-resources语句优势

时间:2013-07-19 06:23:26

标签: java java-7

我正在寻找Java7的新功能。我发现一个是try-with-resources Statement。任何人都可以告诉我它究竟意味着什么?我们应该使用它的原因和位置,以及我们可以利用此功能的地方?即使try语句错过了catch阻止我这也让我感到困惑。

7 个答案:

答案 0 :(得分:73)

之所以引入它是因为Java中使用的一些资源(如SQL连接或流)难以正确处理;例如,在java 6中正确处理 InputStream ,你必须做类似的事情:

InputStream stream = new MyInputStream(...);
try {
    // ... use stream
} catch(IOException e) {
   // handle exception
} finally {
    try {
        if(stream != null) {
            stream.close();
        }
    } catch(IOException e) {
        // handle yet another possible exception
    }
}

你注意到丑陋的双重尝试吗?现在使用try-with-resources可以做到这一点:

try (InputStream stream = new MyInputStream(...)){
    // ... use stream
} catch(IOException e) {
   // handle exception
}
自动调用

close(),如果它抛出IOException,它将被抑制(如Java Language Specification 14.20.3中所指定)。 java.sql.Connection

也是如此

答案 1 :(得分:15)

作为stated in the documentation

  

try-with-resources语句是一个声明一个的try语句   或更多资源。资源是必须在之后关闭的对象   程序完成了。 try-with-resources语句   确保在语句结束时关闭每个资源。任何   实现java.lang.AutoCloseable的对象,包括所有   实现java.io.Closeable的对象可以用作   资源。

     

以下示例从文件中读取第一行。它使用了   BufferedReader的实例,用于从文件中读取数据。的BufferedReader   是程序完成后必须关闭的资源   它:

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}
     

在此示例中,try-with-resources中声明的资源   statement是一个BufferedReader。声明声明出现   在try关键字后面的括号内。班级   Java SE 7及更高版本中的BufferedReader实现了该接口   java.lang.AutoCloseable。因为BufferedReader实例是   在try-with-resource语句中声明,它将被关闭   无论try语句是正常还是突然完成

您可以从here了解更多信息。

答案 2 :(得分:7)

在Java中,如果使用输入或输出流等资源,则必须在使用后关闭它。它也可以抛出异常,因此它必须位于try catch块中。结束必须在finally区块内。这是Java 7之前的最小方法。这有几个缺点:

  • 在关闭之前,您必须检查您的资源是否为null
  • 结算本身可以抛出异常,因此finally必须包含其他try - catch
  • 程序员往往忘记关闭他们的资源

虽然前两个主要是语法问题,但最后一个更为关键。因此,如果您使用try-with语句,您的代码将变得更加清晰,最重要的是:您的资源将始终关闭: - )

答案 3 :(得分:6)

优点是您无需显式关闭在try-with-resources语句中定义的资源。 JVM将负责它。它会自动为您关闭这些资源。

开发人员面临的问题通常是构造try-catch-finally块,因为即使在我们关闭资源的finally块中,我们也必须使用try-catch。有各种try-catch-finally语句结构可以帮助解决这个问题但是try-with-resources语句基本上可以帮助您简化编码结构逻辑。

答案 4 :(得分:5)

Java 9发布后2017年更新

现在使用Java 9我们有更多的语法糖,我们可以在try-catch块之外声明一个资源,但仍然可以正确处理。

让我们以这种处理资源的Java 6方式为例:

InputStream stream = new MyInputStream(...);
try {
    // ... use stream
} catch(IOException e) {
   // handle exception
} finally {
    try {
        if(stream != null) {
            stream.close();
        }
    } catch(IOException e) {
        // handle yet another possible exception
    }
}

在这里,我们可以注意到这个代码非常难看,正如其他答案所指出的那样。

因此Java 7中的解决方案是引入此try-catch-with-resource

try (InputStream stream = new MyInputStream(...)){
    // ... use stream
} catch(IOException e) {
   // handle exception
}

这种符号肯定比前一种更好,但是我们遇到了问题。如果资源(在这种情况下是 strem )之前已经声明但我们想确保在这个块中正确处理它,我们需要这样的技巧:

InputStream stream = new MyInputStream(...)
try (InputStream stream2 = stream) {
   // do something with stream being sure that is going to be closed at the end
} catch(IOException e) {
   // handle exception
}

我们可以注意到这种情况只能用另一条丑陋的代码解决。这就是为什么使用 Java 9改进了Try-With-Resources 引入新语法:

InputStream stream = new MyInputStream(...)
try (stream) {
   // do something with stream being sure that is going to be closed at the end
} catch(IOException e) {
   // handle exception
}

请注意,此语法将导致Java版本8或次要的编译时错误

这是更“自然”的写作方式,即使在大多数用例中我们不需要try块范围之外的资源。 唯一的限制是读者变量应该是最终的,或者只是最终的。

答案 5 :(得分:1)

使用资源试用的好处

  1. 更易读的代码,易于编写。

  2. 自动资源管理。

  3. 减少了代码行数。

  4. 只需关闭资源就不需要最终阻止。

  5. 我们可以在用分号分隔的try-with-resources语句中打开多个资源。例如,我们可以编写以下代码。

  6. 在try-with-resources中打开多个资源时,它会以相反的顺序关闭它们以避免任何依赖性问题。您可以扩展我的资源程序来证明这一点。

  7.   

    public void sampleTryWithResource() {
                try(Connection dbCon = DriverManager.getConnection("url", "user", "password");
                        BufferedReader br = new BufferedReader(new FileReader("C://readfile/input.txt"));) {
                    //...Your Business logic
                } catch (Exception e) {
                    //...Exception Handling
                }
            }
    

答案 6 :(得分:-4)

这个怎么样 - 如果在try {}内部初始化资源,它是否会自动关闭?

try {
            Scanner scanner = new Scanner(new File(csvFile));
            while (scanner.hasNext()) {
                 // do something
            }
            scanner.close();
        }catch(FileNotFoundException fnfe)
        {
            System.err.println(fnfe.getLocalizedMessage());
        }