服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Java try()语句实现try-with-resources异常管理机制操作

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

2022-01-10 13:47bsbhenry Java教程

这篇文章主要介绍了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方法被调用

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

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教程Java8中Stream使用的一个注意事项

    Java8中Stream使用的一个注意事项

    最近在工作中发现了对于集合操作转换的神器,java8新特性 stream,但在使用中遇到了一个非常重要的注意点,所以这篇文章主要给大家介绍了关于Java8中S...

    阿杜7482021-02-04
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    这篇文章主要介绍了Java使用SAX解析xml的示例,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程20个非常实用的Java程序代码片段

    20个非常实用的Java程序代码片段

    这篇文章主要为大家分享了20个非常实用的Java程序片段,对java开发项目有所帮助,感兴趣的小伙伴们可以参考一下 ...

    lijiao5352020-04-06
  • Java教程Java BufferWriter写文件写不进去或缺失数据的解决

    Java BufferWriter写文件写不进去或缺失数据的解决

    这篇文章主要介绍了Java BufferWriter写文件写不进去或缺失数据的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望...

    spcoder14552021-10-18
  • Java教程升级IDEA后Lombok不能使用的解决方法

    升级IDEA后Lombok不能使用的解决方法

    最近看到提示IDEA提示升级,寻思已经有好久没有升过级了。升级完毕重启之后,突然发现好多错误,本文就来介绍一下如何解决,感兴趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java实现抢红包功能

    Java实现抢红包功能

    这篇文章主要为大家详细介绍了Java实现抢红包功能,采用多线程模拟多人同时抢红包,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙...

    littleschemer13532021-05-16
  • Java教程xml与Java对象的转换详解

    xml与Java对象的转换详解

    这篇文章主要介绍了xml与Java对象的转换详解的相关资料,需要的朋友可以参考下...

    Java教程网2942020-09-17
  • Java教程小米推送Java代码

    小米推送Java代码

    今天小编就为大家分享一篇关于小米推送Java代码,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...

    富贵稳中求8032021-07-12