相关文章推荐
大鼻子的奔马  ·  Java ...·  2 月前    · 
喝醉的铁板烧  ·  Intro to JaCoCo | ...·  3 月前    · 
纯真的黑框眼镜  ·  android ...·  1 年前    · 

推荐: Java网络编程汇总

使用try-with-resources优雅关闭资源

JDK1.7之后,引入了 try-with-resources ,使得关闭资源操作无需层层嵌套在 finally 中,代码简洁不少,本质是一个语法糖,能够使用 try-with-resources 关闭资源的类,必须实现 AutoCloseable 接口。

JDK1.7版本之前,传统的关闭资源操作如下:

public static void main(String[] args){
    FileInputStream fileInputStream = null;
    try {
        fileInputStream = new FileInputStream("file.txt");
        fileInputStream.read();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            assert fileInputStream != null;
            fileInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();

可以看到,为了确保资源关闭正常,需要finally中再嵌入try-catchtry-catch中打开资源越多,finally嵌套越深,可能会导致关闭资源的代码比业务代码还要多。

但是使用了try-with-resources语法后,上面的例子可改写为:

try(FileInputStream fileInputStream1 = new FileInputStream("file.txt")){
    fileInputStream1.read();
} catch (IOException e) {
    e.printStackTrace();

如何判读资源是否真的被关闭了呢,我们手写个Demo:

实现AutoCloseable接口的资源类。

class MyResource implements AutoCloseable{
    public void open(){
        System.out.println("resource is open!");
    @Override
    public void close() throws Exception {
        System.out.println("resource is close!");
public static void main(String[] args){
    try(MyResource myResource = new MyResource()){
        myResource.open();
    } catch (Exception e) {
        e.printStackTrace();

输出如下,可以看到close方法被自动调用了。

resource is open!
resource is close!

底层原理是什么呢,看一下编译后的class文件:

try {
        MyResource myResource = new MyResource();
        Throwable var2 = null;
        try {
            myResource.open();
        } catch (Throwable var12) {
            var2 = var12;
            throw var12;
        } finally {
            if (myResource != null) {
                if (var2 != null) {
                    try {
                        myResource.close();
                    } catch (Throwable var11) {
                        var2.addSuppressed(var11);
                } else {
                    myResource.close();
    } catch (Exception var14) {
        var14.printStackTrace();

很明显,编译器生成了finally代码块,并在其中调用了close 方法,同JDK1.7之前的关闭资源操作的实现原理是相同的,但是可以看到,这里多调用了一个addSuppressed方法,这么做其实是为了处理异常屏蔽,什么是异常屏蔽,首先,我们先修改一下刚刚的Demo,使资源类在openclose方法中抛出异常,并且使用JDK1.7之前的关闭资源的方法,资源类以及调用方代码修改如下:

public void open() throws IOException {
    System.out.println("resource is open!");
    throw new IOException("open() exception!");
@Override
public void close() throws Exception {
    System.out.println("resource is close!");
    throw new IOException("close()  exception!");
public static void main(String[] args) throws Exception {
    MyResource myResource = null;
    try{
        myResource = new MyResource();
        myResource.open();
    }finally {
        try {
            myResource.close();
        } catch (Exception e) {
            e.printStackTrace();

控制台打印如下:
在这里插入图片描述

open方法抛出的异常被自动忽略了,而异常信息丢失将导致程序调试困难,所以try-with-resources语法中加入了addSuppressed处理异常屏蔽,现在修改Demo为使用try-with-resource关闭资源,调用方代码如下:

public static void main(String[] args) throws Exception {
    try(MyResource myResource = new MyResource()){
        myResource.open();

控制台打印如下图:
在这里插入图片描述
异常信息中多了提示:close方法中抛出的异常被open方法中抛出的异常抑制了。

使用try-catch-resources,并不能完全保证资源被关闭,在Java BIO中,使用了大量的装饰器模式,调用装饰类的close方法时实际是在调用其中包裹的流的close方法,但是在调用包裹的流的close方法时,装饰类还做了一些其他的操作,如果这些操作出现异常,将导致包裹流的close方法被跳过,资源没有被正确关闭,正确的方式是在try中单独声明底层资源类以及装饰类,这样就可以保证,每个类的close方法都被调用。

使用try-with-resources优雅关闭资源JDK1.7之后,引入了try-with-resources,使得关闭资源操作无需层层嵌套在finally中,代码简洁不少,本质是一个语法糖,能够使用try-with-resources关闭资源的类,必须实现AutoCloseable接口。JDK1.7版本之前,传统的关闭资源操作如下:public static void main(Stri...
使用sonarqube检查代码时报错 Use try-with-resources or close this “FileInputStream” in a “finally” clause. 原始代码是这样的,当时是个阻断的bug, private static void copyFile(String copyFile, String newFile) throws Exception { FileInputStream fis = null; FileOutpu
今天写完代码,用sonar跑了一下,发现报 Use try-with-resources or close this "workbook" in a "finally" clause. try catch之后没有 关闭workbook 在catch后加上关闭代码 finally{ if(null != workbook) {
自己的理解: try-with-resources是JDK7的新语法结构,主要功能是自动关闭资源而不需要在finally里面手动close()关闭, 而且最重要的是,try块中的异常不会被close()引起的异常压制——因为不需要写close()了,系统自动帮你完成——前提是实现了AutoCloseable或Closeable接口的类或接口。 Throwable.getSuppressed方...
Sonar常见问题及修改建议(202001):https://blog.csdn.net/libusi001/article/details/103717457 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 一、报错信息 Use try-with-resources or close this "BufferedOutputStream"...
Oracle官方文档: http://docs.oracle.com/javase/7/docs/technotes/guides/language/try-with-resources.html Java SE 7以及后续版本中, 增加了 try-with-resources 语句,与传统 try 语句在结构上看在 try 后多了一个括号() try-with-resources语句是一...
try-with-resources是jdk1.7加入的机制。可以保证资源使用后正常关闭try-with-resources比起try-catch-finally使代码更加简洁。 try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true)))) { Iterator<String> iterator = list.iter.
我们知道,在Java编程过程中,如果打开了外部资源(文件、数据库连接、网络连接等),我们必须在这些外部资源使用完毕后,手动关闭它们。因为外部资源不由JVM管理,无法享用JVM的垃圾回收机制,如果我们不在编程时确保在正确的时机关闭外部资源,就会导致外部资源泄露,紧接着就会出现文件被异常占用,数据库连接过多导致连接池溢出等诸多很严重的问题。 二、传统的资源关闭方式 为了确保外部资源一...
文章目录一、为什么引入 try-with-resource?二、try-with-resource 的使用三、原理探究四、注意事项 一、为什么引入 try-with-resource? 所有被打开的系统资源,比如流、文件或者Socket连接等,都需要被开发者手动关闭,否则随着程序的不断运行,资源泄露将会累积成重大的生产事故。 当然可以将处理资源关闭的代码写在finally块中。 然而,如果你同时打开了多个资源,那么将会出现噩梦般的场景: public class Demo { public stat
Sonar:修复Use try-with-resources or close this “xxx” in a “finally” clause Use try-with-resources or close this "xxx" in a "finally" clause 问题不通过代码位置 try { Data da = new Datat(""); Dataa dd = new Dataa(); dd.send(da
try-with-resources是Java 7中引入的一种新的异常处理机制,用于自动关闭资源使用try-with-resources可以避免手动关闭资源的繁琐操作,同时也可以确保资源使用完毕后被正确关闭,避免资源泄露。 下面是try-with-resources使用示例: try (FileInputStream fis = new FileInputStream("test.txt"); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr)) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } catch (IOException e) { e.printStackTrace(); 在这个示例中,我们使用try-with-resources来读取一个文本文件。在try语句块中,我们创建了三个资源对象:FileInputStream、InputStreamReader和BufferedReader。这些资源对象都实现了AutoCloseable接口,因此可以在try语句块结束时自动关闭。 在try语句块中,我们使用BufferedReader的readLine()方法逐行读取文本文件,并将每行输出到控制台。如果在读取过程中发生了IOException异常,我们将在catch语句块中捕获并打印异常信息。 需要注意的是,try-with-resources语句块中的资源对象必须实现AutoCloseable接口,否则无法自动关闭。如果需要在try语句块结束时执行一些清理操作,可以在资源对象的close()方法中实现。