zoukankan      html  css  js  c++  java
  • Java 基础 AutoCloseable & Closeable

    Overview

    CloseableAutoCloseable都是接口,且都只定义了一个close()方法。
    Closeable: 定义于 java.io包中,于JDK5添加;
    AutoCloseable: 定义于java.lang包中, 于JDK7添加;

    AutoCloseable.java

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

    JDK7开始,Closeable扩展了AutoCloseable

    Closeable.java

    public interface Closeable extends AutoCloseable {
        public void close() throws IOException;
    }
    
    

    因此从JDK7开始,CloseableAutoCloseable具有相同的功能,因此下面只介绍AutoCloseable

    AutoCloseable 是什么

    AutoCloseable是一个接口,只定义了一个close()方法。接口是什么?是为了给某些类实现的,它强制要求这个类提供接口定义的方法。所有实现AutoCloseable接口的类都必须提供close()方法。
    那什么样的类需要实现AutoCloseable(Closeable)接口呢? 看看它定义的方法, close()。看名字就知道所有实现这个接口的类都必须提供关闭的方法,关闭的自然是资源, 比如各类输入输出流资源, Socket等。
    常见的实现了AutoCloseable接口的类有:
    BufferedInputStream, BufferedOutputStream
    BufferedReader, BufferedWriter
    FileInputStream, FileOutputStream
    FileReader, FileWriter
    InputStream, OutputStream
    PrintWriter, PrintStream
    Reader, Writer
    Scanner, SSLServerSocker, SSLSocket等等等等

    为什么要使用AutoCloseable

    JDK1.7以前,如果我们要用到上面的这些资源类,因为没有他们没有实现AutoCloseable接口, 正常的做法是需要使用try-finally结构, 在finally中手动的释放资源:

            //JDK1.7之前,释放资源方式
             FileInputStream fileInputStream = null;
             try {
                 fileInputStream = new FileInputStream("");
             } catch (FileNotFoundException e) {
                 e.printStackTrace();
             } finally {
                 try {
                     fileInputStream.close();
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
    

    这么做的坏处是:
    1、自己要手动写代码做关闭的逻辑;
    2、有时候还会忘记关闭一些资源;
    3、关闭代码的逻辑比较冗长,不应该是正常的业务逻辑需要关注的

    为了解决需要手动释放资源的问题, 在JDK1.7中引入了AutoCloseable接口,凡是实现了这个接口的资源类在使用的时候采用另外一种语法,可以使得免于手动关闭这些资源类。

    怎么使用AutoCloseable

    使用已经实现了AutoCloseable接口的资源类

    对于实现了AutoCloseable接口的类的实例,将其放到try后面的小括号中,这种语法我们称之为:带资源的try语句,在try结束的时候,会自动将这些资源关闭(调用close方法)。

            //1.7之后,只要实现了AutoCloseable接口
             try (FileInputStream fileInputStream2 = new FileInputStream("");
                    Reader rd = new Reader()) {
             } catch (FileNotFoundException e) {
                 e.printStackTrace();
             } catch (IOException e) {
                 e.printStackTrace();
    

    注意这里申请资源的语句放在了紧跟着try的小括号中,这属于JDK1.7的新语法。只要用这样的语法申请实现了AutoCloseable接口的资源类,就无需使用finally块手动释放这些资源。

    带资源的try语句的3个关键点

    1. 由带资源的try语句管理的资源必须是实现了AutoCloseable接口的类的对象。
    2. try代码中声明的资源被隐式声明为final
    3. 通过使用分号分隔每个声明可以管理多个资源。

    定义自己的资源类,实现AutoCloseable接口

    对于自己定义的资源类,如果也想像FileInputStream一样在使用的时候用带资源的try语句实现自动释放,做法就很显然: 让这个类去实现AutoCloseable接口并重写close()方法, 在重写的close()方法中提供释放资源的语句。

    class MyResource implements AutoCloseable {
        /**
        对这个接口的实现,规范强烈建议close()是幂等的,也就是说多次调用close()方法和一次调用的结果是一样的。
        */
        @Override
        public void close() throws Exception {
            //添加释放资源的语句
            System.out.println("close resource");
        }
    
        public void readResource() {
            //提供资源的方法
            System.out.println("read resource");
        }
    }
    

    这样定义了MyResource类后,就可以像如下方式使用它:

            //示例,使用自己定义的资源类,它实现了AutoCloseable接口
            try (MyResource myResource = new MyResource()) {
                myResource.readResource();
                myResource2.readResource();
            } catch (Exception e) {
                e.printStackTrace();
            }
    

    注意

    虽然在JDK1.7之后AutoCloseableCloseable具有一样的功能,但一般实现自己的资源类的时候我们让它实现AutoCloseable类。CloseableAutoCloseable更早出现(JDK5),在JDK7之前它提供了一套关闭资源的方法,但是后来的AutoCloseable可以用更好的方法来关闭资源,于是从JDK7开始弃用了之前Closeable接口关闭资源的方法,而让它去扩展AutoCloseable接口,这样先前实现Closeable类的方法也可以过度到AutoCloseable的解决方案中来。
    需要注意的是AutoCloseable定义在java.lang包中,这个包在java启动时自动加载到环境,所以使用AutoCloseable时无需额外引包;而Closeable定义在java.io中,如果要使用这个接口需要手动引入java.io.Closeable

    参考 Java IO之AutoCloseable,Closeable和Flushable接口

  • 相关阅读:
    [.Net 5.0] 笔记
    java计算两个字符串日期的相差天数
    记一个使用fyne-cross编译的坑
    windows gcc 遇到的问题解决
    异步处理在支付环节的应用
    怎么修复 "replaceAll is not a function" JavaScript Error?
    Js生成随机数 生成随机字符串的5种方法
    json-bigint的介绍和使用-解决Javascript的有关大整数问题
    国产操作系统——银河麒麟V10 SP1使用小结
    【转载】 银河麒麟V10系统安装U盘制作
  • 原文地址:https://www.cnblogs.com/greatLong/p/11951739.html
Copyright © 2011-2022 走看看