Java7试用资源声明的优势
我正在看Java7的新function。 我发现一个是试用资源的声明 。 谁能告诉我究竟是什么意思? 为什么和在哪里我们应该使用它,在哪里我们可以得到这个function的优势? 甚至try
声明错过了为我迷惑的块。
它是由于Java中使用的一些资源(如SQL连接或stream)难以正确处理而引入的; 作为一个例子,在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 (InputStream stream = new MyInputStream(...)){ // ... use stream } catch(IOException e) { // handle exception }
而close()会自动调用,如果抛出一个IOException,它将被压制(如Java语言规范14.20.3中所指定的)。 java.sql.Connection也是如此
正如文件中所述 :
try-with-resources语句是声明一个或多个资源的try语句。 资源是程序结束后必须closures的对象。 try-with-resources语句确保每个资源在语句结束时closures。 任何实现
java.lang.AutoCloseable
对象(包括所有实现java.io.Closeable
对象)都可以用作资源。以下示例从文件读取第一行。 它使用BufferedReader的实例从文件中读取数据。 BufferedReader是程序完成后必须closures的资源:
static String readFirstLineFromFile(String path) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } }
在这个例子中,在try-with-resources语句中声明的资源是一个BufferedReader。 声明语句出现在try关键字之后的括号内。 Java SE 7及更高版本中的类BufferedReader实现了接口java.lang.AutoCloseable。 因为BufferedReader实例是在try-with-resource语句中声明的,所以无论try语句是正常还是突然完成
你可以从这里阅读更多。
在Java中,如果使用input或输出stream等资源,则在使用后必须closures它。 它也可以抛出exception,所以它必须在try
catch
块中。 closures必须在finally
块。 这是Java 7之前的最低速度。这有几个缺点:
- 在closures它之前,你必须检查你的资源是否为
null
- closures本身可以抛出exception,所以你
finally
不得不包含另一个try
–catch
- 程序员往往忘记closures他们的资源
虽然前两个主要是语法问题,但最后一个更重要。 所以,如果你使用try-with语句,你的代码会变得更清洁,最重要的是:你的资源将永远被closures:-)
好处是您不需要明确地closures您在try-with-resources Statement中定义的资源。 JVM会照顾它。 它会自动为你closures这些资源。
一般来说,开发人员面临的问题是构buildtry-catch-finally块,因为即使在最后closures资源的地方,我们也必须使用try-catch。 try-catch-finally语句有各种结构来帮助解决这个问题,但是试用资源语句基本上可以帮助您减轻编码结构的逻辑。
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
的解决scheme是引入这个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或次要版本的编译时错误
这是更“自然”的写作方式,尽pipe在大多数情况下,我们不需要超出try块范围的资源。 唯一的限制是读者variables应该是有效的或者只是最终的。
使用资源尝试的好处
-
更易读的代码,易于编写。
-
自动资源pipe理。
-
代码行数减less。
-
没有必要最后阻止只是closures资源。
-
我们可以在以分号分隔的try-with-resources语句中打开多个资源。 例如,我们可以写下面的代码。
-
当在资源尝试中打开多个资源时,它将以相反的顺序closures它们以避免任何依赖性问题。 你可以扩展我的资源程序来certificate这一点。
那么怎么样 – 如果资源在try {}中初始化,它会自动closures吗?
try { Scanner scanner = new Scanner(new File(csvFile)); while (scanner.hasNext()) { // do something } scanner.close(); }catch(FileNotFoundException fnfe) { System.err.println(fnfe.getLocalizedMessage()); }