AutoCloseable 使用学习

介绍

无论是使用文件 IO 流,还是网络 Socket 流,都免不了调用 close() 将流关闭。如果需要操作的流过多,就会导致混乱。一旦忘记将关闭方法放到 finally 中,很有可能出现流未被关闭,占用大量内存空间的问题。在try-with-resources结构中会自动调用AutoCloseable实现类的close()方法,简化了流程,提高了代码效率。

Demo

try-catch-finally 与 try-with-resource

  • try-catch-finally
AC ac = null;
AC2 ac2 = null;
try {
    ac = new AC();
    ac2 = new AC2();
} catch (Exception e) {
} finally {
    ac.close();
    ac2.close();
}
  • try-with-resource
try (AC ac = new AC();
     AC2 ac2 = new AC2()) {
     sout("done~");
}

try-with-resource语法的目的是提高Java开发人员的效率,使得他们不需要在编写代码时考虑资源释放问题,大多数的这类"清理"问题是由于异常发生时清理方法没有被调用产生。

测试

准备工作

AC.java

public class AC implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("Program has been closed pretended.");
    }

    //默认静态方法,在被实例化时执行
    static {
        System.out.println("Program running.");
    }
}

AC2.java

public class AC2 implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("Program 2 has been closed pretended.");
    }

    static {
        System.out.println("Program 2 running.");
    }
}

Main1.java

public class Main {
    public static void main(String[] args) {
        try (AC ac = new AC();
             AC2 ac2 = new AC2()) {
            //这里假装执行了有用的代码
            Thread.sleep(2000);
        } catch (Exception e) {
            System.out.println("error~");
        }
        System.out.println("end~");
    }
}

Main2.java

package autocloseable;

public class Main2 {
    public static void main(String[] args) {
        AC ac = new AC();
        AC2 ac2 = new AC2();
        try {
            System.out.println("done~");
        } catch (Exception e) {
            System.err.println("error~");
        } finally {
            // 显示调用
//            try {
//                ac.close();
//                ac2.close();
//            } catch (Exception ex) {
//                ex.printStackTrace();
//            }
        }
    }
}

测试结果

Main1.java

Program running.
Program 2 running.
Program 2 has been closed pretended.
Program has been closed pretended.
end~

Main2.java

Program running.
Program 2 running.
done~
// 以下显示调用才会触发
Program has been closed pretended.
Program 2 has been closed pretended.

通过上述的测试对比,我们知道,AutoCloseable#close()方法在try-with-resource结构块结束的时候自动调用,方法调用完成之后,再继续向下执行。如果是try-catch-finally结构块,则需要在finally接口中显示调用close()方法。

总结

  • 资源必须是AutoCloseable的子类型,如果不是的话会得到一个编译期错误。
  • 资源都是隐式final的,也就是说即便没有使用final,这些资源也都是final的。如果尝试为资源变量赋值会得到一个编译期错误。
  • 资源关闭的顺序与定义的顺序正好相反。如上述的ac, ac2。这么做可以构建嵌套的流,然后从外向内关闭流,这要比按顺序关闭更好(也就是说,可以在底层的流关闭前先清空缓存)。

参考链接

大白话之 AutoClosable 接口

你可能感兴趣的:(Java技术学习,java)