千家信息网

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

发表于:2024-11-17 作者:千家信息网编辑
千家信息网最后更新 2024年11月17日,Java try()语句实现try-with-resources异常管理机制的操作方法,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
千家信息网最后更新 2024年11月17日Java try()语句实现try-with-resources异常管理机制的操作方法

Java try()语句实现try-with-resources异常管理机制的操作方法,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

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

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

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

public interface AutoCloseable{    public void close() throws Exception;}

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

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

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(),括号内可以包含多个语句。

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方法中打印信息

package test; public class TestAutoCloseable implements AutoCloseable{ public TestAutoCloseable() {  System.out.println("class TestAutoCloceable"); } public void close() {  System.out.println("function close() executed"); }}

测试代码

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以前,我们关闭资源的方式如下

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,方便理解

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方法被调用。多个语句使用分号断开。

反编译之后我们可以看见

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);  }}

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

var2.addSuppressed(var11);

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

源码里面有解释

 /**     * 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语句。

关于Java try()语句实现try-with-resources异常管理机制的操作方法问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。

0