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

目录
  • Java try()语句实现try-with-resources异常管理机制
    • 不使用try-with-resources时,使用的资源要在finally中进行释放
    • 使用try-with-resources时
    • 自定义AutoCloseable实现
  • try-with-resources语句优雅的关闭资源
    • 在java1.7以前,我们关闭资源的方式如下
    • 我们先直接上一个demo,方便理解
    • 反编译之后我们可以看见
    • 源码里面有解释
    • 总结

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

java7 新增特性,对于try语句块中使用到的资源,不再需要手动关闭,在语句块结束后,会自动关闭,类似于python的with..as的用法。

利用这个特性,需要实现AutoCloseable接口,只有一个close方法,实现关闭资源的操作。

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

所有的流,都实现了这个接口,可以在try()中进行实例化。自定义的类只要实现了这个接口,也可以使用这个特性。

不使用try-with-resources时,使用的资源要在finally中进行释放

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(),括号内可以包含多个语句。

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方法中打印信息

package test;
public class TestAutoCloseable implements AutoCloseable{
 public TestAutoCloseable() {
  System.out.println("class TestAutoCloceable");
 }
 public void close() {
  System.out.println("function close() executed");
 }
}

测试代码

package test;
public class TestFeature {
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  try(TestAutoCloseable testAutoCloseable = new TestAutoCloseable()){
  }
 }
}

结果close方法被调用

try-with-resources语句优雅的关闭资源

在Java编程过程中,如果打开了外部资源(文件、数据库连接、网络连接等),我们必须在这些外部资源使用完毕后,手动关闭它们。

因为外部资源不由JVM管理,无法享用JVM的垃圾回收机制,如果我们不在编程时确保在正确的时机关闭外部资源,就会导致外部资源泄露,紧接着就会出现文件被异常占用,数据库连接过多导致连接池溢出等诸多很严重的问题。

在java1.7以前,我们关闭资源的方式如下

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,方便理解

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方法被调用。多个语句使用分号断开。

反编译之后我们可以看见

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);
  }
}

通过反编译的代码,大家可能注意到代码中有一处对异常的特殊处理:

var2.addSuppressed(var11);

这是try-with-resource语法涉及的另外一个知识点,叫做异常抑制。当对外部资源进行处理(例如读或写)时,如果遭遇了异常,且在随后的关闭外部资源过程中,又遭遇了异常,那么你catch到的将会是对外部资源进行处理时遭遇的异常,关闭资源时遭遇的异常将被“抑制”但不是丢弃,通过异常的getSuppressed方法,可以提取出被抑制的异常。

源码里面有解释

 /**
     * 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语句。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 如何使用try-with-resource机制关闭连接

    使用try-with-resource机制关闭连接 JAVA的一大特性就是JVM会对内部资源实现自动回收 即自动GC,给开发者带来了极大的便利.但是JVM对外部资源的引用却无法自动回收,例如数据库连接,网络连接以及输入输出IO流等,这些连接就需要我们手动去关闭,不然会导致外部资源泄露,连接池溢出以及文件被异常占用等. 传统的手动释放外部资源一般放在 try{}catch(){}finally{}机制的finally代码块中,因为finally代码块中语句是肯定会被执行的,即保证了外部资源最后一定

  • 深入理解Java基础之try-with-resource语法糖

    背景 众所周知,所有被打开的系统资源,比如流.文件或者Socket连接等,都需要被开发者手动关闭,否则随着程序的不断运行,资源泄露将会累积成重大的生产事故. 在Java的江湖中,存在着一种名为finally的功夫,它可以保证当你习武走火入魔之时,还可以做一些自救的操作.在远古时代,处理资源关闭的代码通常写在finally块中.然而,如果你同时打开了多个资源,那么将会出现噩梦般的场景: public class Demo { public static void main(String[] arg

  • Java try-with-resource语法使用解析

    背景 众所周知,所有被打开的系统资源,比如流.文件或者Socket连接等,都需要被开发者手动关闭,否则随着程序的不断运行,资源泄露将会累积成重大的生产事故. 在Java的江湖中,存在着一种名为finally的功夫,它可以保证当你习武走火入魔之时,还可以做一些自救的操作.在远古时代,处理资源关闭的代码通常写在finally块中.然而,如果你同时打开了多个资源,那么将会出现噩梦般的场景: public class Demo { public static void main(String[] arg

  • Java使用 try-with-resources 实现自动关闭资源的方法

    1. 在Java1.7之前,我们需要通过下面这种方法, 在finally中释放资源,这种方法有点繁琐. BufferedReader br = null; String str; try { br = new BufferedReader(new FileReader("")); while ((str = br.readLine()) != null) { System.out.println(str); } } catch (IOException e) { e.printStac

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

    目录 Java try()语句实现try-with-resources异常管理机制 不使用try-with-resources时,使用的资源要在finally中进行释放 使用try-with-resources时 自定义AutoCloseable实现 try-with-resources语句优雅的关闭资源 在java1.7以前,我们关闭资源的方式如下 我们先直接上一个demo,方便理解 反编译之后我们可以看见 源码里面有解释 总结 Java try()语句实现try-with-resources

  • 浅谈Java finally语句到底是在return之前还是之后执行(必看篇)

    网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行?很多人都说不是,当然他们的回答是正确的,经过我试验,至少有两种情况下finally语句是不会被执行的: (1)try语句没有被执行到,如在try语句之前就返回了,这样finally语句就不会执行,这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到. (2)在try块中有System.exit(0);这样的语句,System.exit(0);

  • Caused by: java.lang.ClassNotFoundException: org.objectweb.asm.Type异常

    今天做了一个Map转java对象的例子,用了一种比较简单的方法,就是通过net.sf.cglib.beans.BeanMap类中的方法进行转换.结果在一切准备就绪,执行的时候报错了,如下: Exception in thread "main" java.lang.NoClassDefFoundError: org/objectweb/asm/Type at net.sf.cglib.core.TypeUtils.parseType(TypeUtils.java:184) at net.

  • Java 如何优雅的抛出业务异常

    记得上学的时候学习英语,每个英语老师说到英语翻译的时候都会说英语翻译要做到"信.达.雅".如今做了一名程序员竟然体会我还是想用这三种境界来要求自己,恰逢自己现在所做之项目偏业务,代码的优雅显得格外重要.所以我就想写点这方面的东西,今天就先来说说如何优雅的抛出业务异常.代码千千万,只希望对自己和对大家有所帮助. 针对java开发者而言,异常的重要性不言而喻,这里也不再赘述.今天主要说说在业务中利用异常处理机制来实现业务异常的优雅提示. 首先,我们定义一个异常编码接口 public int

  • Java 常见的几种内存溢出异常的原因及解决

    内存溢出的异常有很多,并且每种内存溢出都会有不同的异常信息和解决方式,下面会列出常见的几种内存溢出异常 堆内存溢出 java.lang.OutOfMemoryError: Java heap space 原因: 当堆内存不足,并且已经达到JVM设置的最大值,无法继续申请新的内存,存活的对象在堆内存中无法被回收,那么就会抛出该异常,表示堆内存溢出. 当一次从数据库查询大量数据,堆内存没有足够的内存可以存放大量的数据 大量的强引用对象在堆内存中存活,GC无法回收这些对象,新创建的对象在新生代无法进行

  • Java解析xml文件遇到特殊符号异常的情况(处理方案)

    在一次Java解析xml文件的开发过程中,使用SAX解析时,出现了这样一个异常信息: Error on line 60 of document : 对实体 "xxx" 的引用必须以 ';' 分隔符结尾; 我打开xml文件后,发现该"xxx"符号之前跟着一个"&"符号,后来了解到,这类符号在xml里属于一种特殊符号,而特殊符号若没用转义符表示,直接用到xml文件里,就会在使用SAX等方式做解析时出现奇怪的异常. 其实,这都是因为这些特殊字符

  • Java十分钟掌握数组与常见异常

    数组的定义 1:单个变量能存储信息 2:用来存储具有相同数据类型的数据集合,可以使用共同的名字来引用数组中存储的数据. 特点 数组可以存储任何类型的数据,包括原始数据类型和引用数据类型,但是一旦指定了数组的类型之后,就只能用来存储指定类型的数据. 数组的使用 声明一个数组变量来存放该数组 语法 数据类型 [] 数组名 数据类型 数组名[] //声明一个int类型 名为 numebr 的数组 int [] number; int number []; //以上两种方法都可以 创建一个新的数组对象并

  • javascript中的try catch异常捕获机制用法分析

    本文实例讲述了javascript中的try catch异常捕获机制用法.分享给大家供大家参考,具体如下: 1.跟Java一样,JavaScript也具有try catch块,进行异常捕获的机制. (1)典型的try catch语句 try{ } catch{ } finally{ } 跟java中一样,JS中最为典型的try catch语句也同样分为了三个部分,try用于捕获异常,catch用于处理异常,而finally用于关闭资源等后续操作. 举例: try{ throw "error&qu

  • python自动化测试之异常及日志操作实例分析

    本文实例讲述了python自动化测试之异常及日志操作.分享给大家供大家参考,具体如下: 为了保持自动化测试用例的健壮性,异常的捕获及处理,日志的记录对掌握自动化测试执行情况尤为重要,这里便详细的介绍下在自动化测试中使用到的异常及日志,并介绍其详细的用法. 一.日志 打印日志是很多程序的重要需求,良好的日志输出可以帮我们更方便的检测程序运行状态.Python标准库提供了logging模块,切记Logger从来不直接实例化,其好处不言而喻,接下来慢慢讲解Logging模块提供了两种记录日志的方式.

  • Python try except异常捕获机制原理解析

    当你执行大型程序的时候,突然出现exception,会让程序直接停止,这种对服务器自动程序很不友好,而python有着较好的异常捕获机制,不会立刻终止程序. 这个机制就是try-except. 1. 发生异常时可配置备用程序 aa = [1,2,4,5,7,0,2] for ii in aa: try: h = 2/ii print(h) except: #发生异常时备用 h = 2/(ii+1) print(h) 2. 单个异常捕获 dict_ = {} try: print(dict_['t

随机推荐