java8学习第二篇:try-with-resources

本文详细介绍了Java中try-with-resources语法特性的使用方法及其工作原理。通过对比常规资源关闭方式和try-with-resources的区别,展示了如何利用这一特性简化代码并避免资源泄漏的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java8里的一个新语法特性:try-with-resources。

这个语法特性其实从java7里就有了,不过java8的sample里依然有这个。

try-with-resources的特性就是,在try( ...)里声明的资源,会在try-catch代码块结束后自动关闭掉。

 

废话不说,先上代码后分析。

 


 
  1. public class AutoCloseTest {

  2. public static void main(String[] args) {

  3. testNormalOutput(args[0]);

  4. testAutoCloseWithTryCatch(args[1]);

  5. }

  6.  
  7. private static void testNormalOutput(String filepath){

  8. OutputStream global_out = null;

  9. BufferedWriter writer ;

  10. try {

  11. OutputStream out = out = new FileOutputStream(filepath);

  12. global_out = out;

  13. out.write((filepath + "inside try catch block").getBytes());

  14. } catch (Exception e) {

  15. e.printStackTrace();

  16. }

  17.  
  18. try{

  19. if(global_out!=null){

  20. global_out.write(" \t\r outside try catch block".getBytes());

  21. global_out.close();

  22. }

  23. } catch (Exception e){

  24. e.printStackTrace();

  25. }

  26. }

  27.  
  28. private static void testAutoCloseWithTryCatch(String filepath){

  29. OutputStream global_out = null;

  30. try(OutputStream out = new FileOutputStream(filepath);) {

  31. global_out = out;

  32. out.write((filepath+"inside try catch block").getBytes());

  33. } catch (Exception e) {

  34. e.printStackTrace();

  35. }

  36. try{

  37. if(global_out!=null){

  38. global_out.write(" \t\r outside try catch block".getBytes());

  39. global_out.close();

  40. }

  41. } catch (Exception e){

  42. e.printStackTrace();

  43. }

  44. }

  45. }


运行

java AutoCloseTest d:/a.txt d:/b.txt

然后发现

a.txt里的内容是

 

d:/a.txt inside try catch block  	outside try catch block

 

b.txt里的内容是

 

d:/b.txt inside try catch block

 

没错,b.txt的后半段代码没有执行

同时控制台还打印出


 
  1. java.io.IOException: Stream Closed

  2. at java.io.FileOutputStream.writeBytes(Native Method)

  3. at java.io.FileOutputStream.write(FileOutputStream.java:294)

  4. at trywithresources.AutoCloseTest.testAutoCloseWithTryCatch(AutoCloseTest.java:46)

  5. at trywithresources.AutoCloseTest.main(AutoCloseTest.java:11)

  6. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

  7. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

  8. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

  9. at java.lang.reflect.Method.invoke(Method.java:483)

  10. at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)


这是因为在testAutoCloseWithTryCatch方法里,global_out所指向的out对象已经在第一次try-catch之后被关闭了

在第二次对这个已经关闭的流里输出内容时,就会报Stream Closed错误。

 

--------------------*************************-----------------------********************

 

那么try-with-resources是如何工作的呢?它和finally的工作谁在前呢?我们可以做一个小测试


 
  1. private static void testAutoClose() {

  2. AutoCloseable global_obj1 = null;

  3. AutoCloseable global_obj2 = null;

  4. try(AutoCloseable obj1 = new AutoClosedImpl("obj1");

  5. AutoCloseable obj2 = new AutoClosedImpl("obj2");){

  6. global_obj1= obj1;

  7. int i = 1/0;

  8. global_obj2= obj2;

  9. } catch (Exception e) {

  10. e.printStackTrace();

  11. }finally{

  12. try{

  13. System.out.println("before finally close");

  14. if(global_obj1!=null){

  15. global_obj1.close();

  16. }

  17. if(global_obj2!=null){

  18. global_obj2.close();

  19. }

  20. System.out.println("after finally close");

  21. } catch(Exception e){

  22. e.printStackTrace();

  23. }

  24. }

  25. }

  26.  
  27. private static class AutoClosedImpl implements AutoCloseable{

  28. private String name;

  29. public AutoClosedImpl(String name){

  30. this.name = name;

  31. }

  32. @Override

  33. public void close() throws Exception {

  34. System.out.println(name+" closing");

  35. }

  36. }


 


执行testAutoClose()方法,会打印出如下结果


 
  1. obj2 closing

  2. obj1 closing

  3. before finally close

  4. obj1 closing

  5. after finally close

  6. java.lang.ArithmeticException: / by zero

  7. at trywithresources.AutoCloseTest.testAutoClose(AutoCloseTest.java:60)

  8. at trywithresources.AutoCloseTest.main(AutoCloseTest.java:12)

  9. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

  10. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

  11. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

  12. at java.lang.reflect.Method.invoke(Method.java:483)

  13. at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)


从上述代码我们可以观测四件事

1. 凡是实现了AutoCloseable接口的类,在try()里声明该类实例的时候,在try结束后,close方法都会被调用

2. try结束后自动调用的close方法,这个动作会早于finally里调用的方法。

3. 不管是否出现异常(int i=1/0会抛出异常),try()里的实例都会被调用close方法

4. 越晚声明的对象,会越早被close掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值