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

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掉。

猜你喜欢

转载自blog.csdn.net/qq_36838191/article/details/82744237