Java 基础 AutoCloseable & Closeable

摘要:
什么是自动关闭?AutoCloseable是一个仅定义close()方法的接口。实现AutoCloseable接口需要哪些类?ClassMyResourceimplementsAutoCloseable{/**对于此接口的实现,规范强烈建议close()是幂等的,即调用close(多次该方法的结果与单个调用的结果相同。请注意,AutoCloseable是在java中定义的。在lang包中,当java启动时,此包会自动加载到环境中,因此在使用AutoCloseble时无需导入其他包;Closeable是用java定义的。io。如果你想使用这个接口,你需要手动导入java。io。可关闭;参考JavaIO的AutoCloseable、Closeable和Flushable接口

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接口

免责声明:文章转载自《Java 基础 AutoCloseable & Closeable》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇springboot 动态修改定时任务预编译头文件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

drf 准备知识(Web应用模式、 api接口、RESTful API规范和序列化)

程序的客户端有很多:硬件设备,游戏,APP,软件,其他的外部服务端。 什么是静态页面,什么是动态页面? 动态页面(需要查数据库的)是前端需要发请求给后端,后端朝数据库搜索并返回数据,前端再dom渲染数据 静态页面就是死的,页面内容不会发生变化,固定不变的 1. Web应用模式在开发Web应用中,有两种应用模式: 1.前后端不分离[客户端看到的内容和所有界面...

Java连接MySQL数据库实现用户名密码的验证方法 Java语句中sql查询语句'' ""作用

//方法一,可以验证登录,但方法不实用。packagecom.swift; importjava.sql.Connection; importjava.sql.DriverManager; importjava.sql.ResultSet; importjava.sql.SQLException; importjava.sql.Statement...

drf之框架基础

(一)drf基础 全称:django-rest framework 接口:什么是接口、restful接口规范(协议) CBV(基于FBV的基础上形成)、CBV生命周期源码----基于restful规范下的CBV接口 请求生命周期:请求组件、解析组件、响应组件 序列化组件(序列化、反序列化简单来说就是对象转为字符串、字符串转为对象,目的是为传输数据(传给别的...

获取 wx.getUserInfo 接口后续将不再出现授权弹窗,请注意升级(微信小程序开发)

微信小程序开发时,Console 提示:获取 wx.getUserInfo 接口后续将不再出现授权弹窗,请注意升级 错误原因: 直接调用这个方法依旧可以获取用户信息, 但是如果你之前没有点击过那个授权的小弹出框,这个方法就直接报错了,需要你直接去引导用户去授权。 解决方法: 微信更新api后,wx.getUserInfo在开发和体验版本都不能弹出授权窗口...

登录接口需html中的token时,需用requests-html库

在新公司,所负责的业务后台是登录接口需要token, 然后后面的接口需要cookie来调用 解析:需要进入登录页面,在js中找到所需的token,放到登录接口参数中调用, 然后用requests.sesson方式来调用后续的接口完成自动化 1、下载 HTMLSession, pip3 installrequests-html==0.10.0 2、reque...

BTC_ETH_USDT_自动充提币API接口,钱包对接交易所教程!

 以目前市面上用的最多的优盾钱包开放平台为例。 详细的接口文档如下: 官方接口文档链接:https://www.uduncloud.com/gateway-interface 1、目录 1.1、生成地址 1.2、提币 1.3、代付 1.4、交易回调 1.5、校验地址合法性 1.6、获取商户支持币种信息 2、接口明细 1、生成地址 1.1 场景说明 请求指...