好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Java try()语句实现try-with-resources异常管理机制操作

Java try()语句实现try-with-resources异常管理机制

java7 新增特性,对于try语句块中使用到的资源,不再需要手动关闭,在语句块结束后,会自动关闭,类似于python的with..as的用法。

利用这个特性,需要实现AutoCloseable接口,只有一个close方法,实现关闭资源的操作。

?

1

2

3

public interface AutoCloseable{

     public void close() throws Exception;

}

所有的流,都实现了这个接口,可以在try()中进行实例化。自定义的类只要实现了这个接口,也可以使用这个特性。

不使用try-with-resources时,使用的资源要在finally中进行释放

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

package stream;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

public class TestStream {

     public static void main(String[] args) {

         File f = new File( "d:/test.txt" );

         FileInputStream fis = null ;

         try {

             fis = new FileInputStream(f);

         } catch (IOException e) {

             e.printStackTrace();

         } finally {

             // 在finally 里关闭流

             if ( null != fis)

                 try {

                     fis.close();

                 } catch (IOException e) {

                     // TODO Auto-generated catch block

                     e.printStackTrace();

                 }

         }

     }

}

使用try-with-resources时

形式为try(),括号内可以包含多个语句。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

package stream; 

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException; 

public class TestStream { 

     public static void main(String[] args) {

         File f = new File( "d:/lol.txt" );

  

         //把流定义在try()里,try,catch或者finally结束的时候,会自动关闭

         try (FileInputStream fis = new FileInputStream(f)) {

             byte [] all = new byte [( int ) f.length()];

             fis.read(all);

             for ( byte b : all) {

                 System.out.println(b);

             }

         } catch (IOException e) {

             e.printStackTrace();

         } 

     }

}

自定义AutoCloseable实现

在TestAutoCloseable的close方法中打印信息

?

1

2

3

4

5

6

7

8

9

package test;

public class TestAutoCloseable implements AutoCloseable{

  public TestAutoCloseable() {

   System.out.println( "class TestAutoCloceable" );

  }

  public void close() {

   System.out.println( "function close() executed" );

  }

}

测试代码

?

1

2

3

4

5

6

7

8

package test;

public class TestFeature {

  public static void main(String[] args) {

   // TODO Auto-generated method stub

   try (TestAutoCloseable testAutoCloseable = new TestAutoCloseable()){  

   }

  }

}

结果close方法被调用

try-with-resources语句优雅的关闭资源

在Java编程过程中,如果打开了外部资源(文件、数据库连接、网络连接等),我们必须在这些外部资源使用完毕后,手动关闭它们。

因为外部资源不由JVM管理,无法享用JVM的垃圾回收机制,如果我们不在编程时确保在正确的时机关闭外部资源,就会导致外部资源泄露,紧接着就会出现文件被异常占用,数据库连接过多导致连接池溢出等诸多很严重的问题。

在java1.7以前,我们关闭资源的方式如下

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

public class CloseTest {

     public static void main(String[] args){

         FileInputStream fileInputStream = null ;

         try {

             fileInputStream = new FileInputStream( "file.txt" );

             fileInputStream.read();

         } catch (IOException e) {

             e.printStackTrace();

         } finally {

             if (fileInputStream != null ){

                 try {

                     fileInputStream.close();

                 } catch (IOException e) {

                     e.printStackTrace();

                 }

             }

         }

     }

}

为了确保外部资源一定要被关闭,通常关闭代码被写入finally代码块中,关闭资源时可能抛出的异常,于是经典代码就诞生了。

但是,在java1.7版本之后,新增加了一个语法糖,就是try-with-resources语句,

我们先直接上一个demo,方便理解

?

1

2

3

4

5

6

7

8

9

10

11

public class CloseTest {

     public static void main(String[] args) {

         try (FileInputStream fileInputStream1 = new FileInputStream( "file1.txt" );

              FileInputStream fileInputStream2 = new FileInputStream( "file2.txt" )) {

             fileInputStream1.read();

             fileInputStream2.read();

         } catch (IOException e) {

             e.printStackTrace();

         }

     }

}

将外部资源的句柄对象的创建放在try关键字后面的括号中,当这个try-catch代码块执行完毕后,Java会确保外部资源的close方法被调用。多个语句使用分号断开。

反编译之后我们可以看见

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

public static void main(String[] args) {

   try {

     FileInputStream inputStream = new FileInputStream( new File( "test" ));

     Throwable var2 = null ;

 

     try {

       System.out.println(inputStream.read());

     } catch (Throwable var12) {

       var2 = var12;

       throw var12;

     } finally {

       if (inputStream != null ) {

         if (var2 != null ) {

           try {

             inputStream.close();

           } catch (Throwable var11) {

             var2.addSuppressed(var11);

           }

         } else {

           inputStream.close();

         }

       }

     }

   } catch (IOException var14) {

     throw new RuntimeException(var14.getMessage(), var14);

   }

}

通过反编译的代码,大家可能注意到代码中有一处对异常的特殊处理:

?

1

var2.addSuppressed(var11);

这是try-with-resource语法涉及的另外一个知识点,叫做异常抑制。当对外部资源进行处理(例如读或写)时,如果遭遇了异常,且在随后的关闭外部资源过程中,又遭遇了异常,那么你catch到的将会是对外部资源进行处理时遭遇的异常,关闭资源时遭遇的异常将被[抑制]但不是丢弃,通过异常的getSuppressed方法,可以提取出被抑制的异常。

源码里面有解释

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

/**

     * Returns an array containing all of the exceptions that were

     * suppressed, typically by the {@code try}-with-resources

     * statement, in order to deliver this exception.

     *

     * If no exceptions were suppressed or {@linkplain

     * #Throwable(String, Throwable, boolean, boolean) suppression is

     * disabled}, an empty array is returned.  This method is

     * thread-safe.  Writes to the returned array do not affect future

     * calls to this method.

     *

     * @return an array containing all of the exceptions that were

     *         suppressed to deliver this exception.

     * @since 1.7

     */

    public final synchronized Throwable[] getSuppressed() {

        if (suppressedExceptions == SUPPRESSED_SENTINEL ||

            suppressedExceptions == null )

            return EMPTY_THROWABLE_ARRAY;

        else

            return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);

    }

总结一下吧

因为不管什么情况下(异常或者非异常)资源都必须关闭,在jdk1.6之前,应该把close()放在finally块中,以确保资源的正确释放。如果使用jdk1.7以上的版本,推荐使用try-with-resources语句。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/bsbhenry/article/details/87557792

查看更多关于Java try()语句实现try-with-resources异常管理机制操作的详细内容...

  阅读:18次