英文原文:https://www.journaldev.com/592/java-try-with-resources
今天和大家聊一下java中的 “try with resource”用法。通过“try-with-resource”实现资源自动管理,是 java 7的一个重要特性。
(译者注:此处resource,指程序运行中打开的资源,比如:java stream、socket 等)
目录
1.try with resource 介绍
1.1 java 6 资源管理 举例
1.2 java 7 try with resource 举例
2.java try with resource 的好处
3.try with resource 的 异常处理
1.try with resource
本文"resource"指:程序运行结束时,同时必须要关闭的对象。比如,文件资源(java io)或者 数据库连接的JDBC资源 或者 socket连接资源。
在java 7之前,“自动资源管理”的概念是不存在的,且当此“资源”在代码中完成任务后,需明确在try-catch-finally结构的finally块关闭它。当忘记手动关闭资源时,通常会导致内存泄漏以及性能损失。
下面通过一段伪代码来理解 try-with-resource 特性。
1)java 7 之前
try{
//open resources like File, Database connection, Sockets etc
} catch (FileNotFoundException e) {
// Exception handling like FileNotFoundException, IOException etc
}finally{
// close resources
}
2)java 7 实现 try-with-resource
try(// open resources here){
// use resources
} catch (FileNotFoundException e) {
// exception handling
}
// resources are closed as soon as try-catch block is executed.
下面分别使用java6及更老的版本 和 java7 的try-with-resource 来从文件中读取数据并打印。
java 6 资源管理示例:
package com.journaldev.util;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Java6ResourceManagement {
public static void main(String[] args) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("C:\\journaldev.txt"));
System.out.println(br.readLine());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null)
br.close(); //attention here
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
java 7 try-with-resource 示例:
package com.journaldev.util;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Java7ResourceManagement {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader(
"C:\\journaldev.txt"))) {
System.out.println(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.java try with resource 的好处
1)代码可读性更强且容易编写
2)资源自动管理(释放)
3)代码行数减少
4)不再需要finally代码块即可释放资源
5)在try-with-resource声明中,可以通过分号分隔来开启多个资源。如下代码所示:
try (BufferedReader br = new BufferedReader(new FileReader(
"C:\\journaldev.txt"));
java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(FileSystems.getDefault().getPath("C:\\journaldev.txt"), Charset.defaultCharset())) {
System.out.println(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
6)当try-with-resource中打开了多个资源,会按照相反的顺序关闭来避免依赖产生的问题。
java 7 介绍了新的接口“java.lang.AutoCloseable”。如果使用try-with-resource,则必须实现AutoCloseable接口,否则编译时将抛出异常。参考如下代码:
package com.journaldev.util;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.FileSystems;
public class Java7ResourceManagement {
public static void main(String[] args) {
try (MyResource mr = new MyResource()) {
System.out.println("MyResource created in try-with-resources");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Out of try-catch block.");
}
static class MyResource implements AutoCloseable{
@Override
public void close() throws Exception {
System.out.println("Closing MyResource");
}
}
}
上述程序的输出如下:
MyResource created in try-with-resources
Closing MyResource
Out of try-catch block.
如上可见,当try-catch块执行完成后,资源回收的方法被自动调用了。
3.try with resource 的 异常处理
下面说明“try-catch-finally”和“try-with-resources”在异常处理上的不同。
1)如果在try块和finally块同时抛出异常,方法返回的异常信息来源于finally块。
2)对于“try-with-resources”,如果在try块和“try-with-resources”中同时抛出异常,方法返回的异常,是try块中的异常。
为了更好的理解2种不同,参考如下代码:
package com.journaldev.util;
public class Java7ResourceManagement {
public static void main(String[] args) throws Exception {
try {
tryWithResourceException();
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
normalTryException();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
private static void normalTryException() throws Exception {
MyResource mr = null;
try {
mr = new MyResource();
System.out.println("MyResource created in the try block");
if (true)
throw new Exception("Exception in try");
} finally {
if (mr != null)
mr.close();
}
}
private static void tryWithResourceException() throws Exception {
try (MyResource mr = new MyResource()) {
System.out.println("MyResource created in try-with-resources");
if (true)
throw new Exception("Exception in try");
}
}
static class MyResource implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("Closing MyResource");
throw new Exception("Exception in Closing");
}
}
}
上述程序的输出为:
MyResource created in try-with-resources
Closing MyResource
Exception in try
MyResource created in the try block
Closing MyResource
Exception in Closing
由此证明了上述在异常处理上的不同。
that's all for the java 7 try-with-resources.
2019.06.23 周日晚