Java 中的 try-with-resources 详解
在 Java 7 之前,处理资源关闭通常使用 try-catch-finally
块。虽然这种方式可以确保资源被正确关闭,但代码显得冗长且容易出错。Java 7 引入了 try-with-resources
语法,使得资源管理变得更加简洁和安全。本文将详细介绍 try-with-resources
的使用方法和优势。
1 try-catch-finally 的回顾
在介绍 try-with-resources
之前,我们先回顾一下传统的 try-catch-finally
块的使用方法。
示例:
public class TrycatchfinallyDecoder {
public static void main(String[] args) {
BufferedReader br = null;
try {
String path = TrycatchfinallyDecoder.class.getResource("/牛逼.txt").getFile();
String decodePath = URLDecoder.decode(path, "utf-8");
br = new BufferedReader(new FileReader(decodePath));
String str = null;
while ((str = br.readLine()) != null) {
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
在这个例子中,我们使用 try-catch-finally
块来读取文件内容并确保 BufferedReader
资源被正确关闭。虽然这种方式可以确保资源被关闭,但代码显得冗长且容易出错,尤其是在 finally
块中还需要处理 close()
方法可能抛出的异常。
2 try-with-resources 的引入
try-with-resources
语法简化了资源管理,使得代码更加简洁和安全。要使用 try-with-resources
,资源必须实现 AutoCloseable
接口。
示例:
try (BufferedReader br = new BufferedReader(new FileReader(decodePath))) {
String str = null;
while ((str = br.readLine()) != null) {
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
在这个例子中,BufferedReader
资源在 try
块结束后会自动关闭,无需显式调用 close()
方法。
3 多个资源的管理
try-with-resources
语法支持同时管理多个资源,只需在 try
后的括号中声明多个资源即可。
示例:
try (BufferedReader br = new BufferedReader(new FileReader(decodePath));
PrintWriter writer = new PrintWriter(new File(writePath))) {
String str = null;
while ((str = br.readLine()) != null) {
writer.print(str);
}
} catch (IOException e) {
e.printStackTrace();
}
在这个例子中,BufferedReader
和 PrintWriter
资源都会在 try
块结束后自动关闭。
4 自定义资源的管理
如果需要管理自定义资源,只需让资源类实现 AutoCloseable
接口,并提供 close()
方法。
示例:
public class TrywithresourcesCustom {
public static void main(String[] args) {
try (MyResource resource = new MyResource()) {
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyResource implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("关闭自定义资源");
}
}
在这个例子中,MyResource
类实现了 AutoCloseable
接口,并在 close()
方法中执行资源关闭操作。在 try-with-resources
块中使用 MyResource
对象时,close()
方法会自动调用。
反编译后的字节码:
class MyResource implements AutoCloseable {
MyResource() {
}
public void close() throws Exception {
System.out.println("关闭自定义资源");
}
}
public class TrywithresourcesCustom {
public TrywithresourcesCustom() {
}
public static void main(String[] args) {
try {
MyResource resource = new MyResource();
resource.close();
} catch (Exception var2) {
var2.printStackTrace();
}
}
}
编译器主动为try-with-resources
进行了变身,在 try 中调用了 close()
方法。
5 异常处理
try-with-resources
语法在处理异常时更加优雅。如果 try
块中的代码和资源关闭时都抛出异常,try-with-resources
会自动处理这些异常,并将被抑制的异常附加到主异常中。
示例:
class MyResourceOutThrow implements AutoCloseable {
@Override
public void close() throws Exception {
throw new Exception("close()");
}
public void out() throws Exception {
throw new Exception("out()");
}
}
public class TrywithresourcesCustomOutThrow {
public static void main(String[] args) {
try (MyResourceOutThrow resource = new MyResourceOutThrow()) {
resource.out();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
java.lang.Exception: out()
at com.cmower.dzone.trycatchfinally.MyResourceOutThrow.out(TrywithresourcesCustomOutThrow.java:20)
at com.cmower.dzone.trycatchfinally.TrywithresourcesCustomOutThrow.main(TrywithresourcesCustomOutThrow.java:6)
Suppressed: java.lang.Exception: close()
at com.cmower.dzone.trycatchfinally.MyResourceOutThrow.close(TrywithresourcesCustomOutThrow.java:16)
at com.cmower.dzone.trycatchfinally.TrywithresourcesCustomOutThrow.main(TrywithresourcesCustomOutThrow.java:5)
在这个例子中,out()
方法和 close()
方法都抛出了异常。try-with-resources
语法将 close()
方法的异常附加到 out()
方法的异常中,并使用 Suppressed
关键字标记,使得调试更加方便。
反编译后的字节码:
public class TrywithresourcesCustomOut {
public TrywithresourcesCustomOut() {
}
public static void main(String[] args) {
try {
MyResourceOut resource = new MyResourceOut();
try {
resource.out();
} catch (Throwable var5) {
try {
resource.close();
} catch (Throwable var4) {
var5.addSuppressed(var4);
}
throw var5;
}
resource.close();
} catch (Exception var6) {
var6.printStackTrace();
}
}
}
catch
块主动调用了 resource.close()
,并且有一段很关键的代码 var5.addSuppressed(var4)
。
当一个异常被抛出的时候,可能有其他异常因为该异常而被抑制住,从而无法正常抛出。这时可以通过 addSuppressed()
方法把这些被抑制的方法记录下来,然后被抑制的异常就会出现在抛出的异常的堆栈信息中,可以通过 getSuppressed()
方法来获取这些异常。这样做的好处是不会丢失任何异常,方便我们进行调试。
6 思维导图
7 参考链接
深入理解 Java 中的 try with resources
原文地址:https://blog.csdn.net/gaosw0521/article/details/143503940
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!