[Java开发之路](20)try-with-resource 异常声明

Try-with-resources是java7中一个新的异常处理机制,它能够很容易地关闭在try-catch语句块中使用的资源。

在java7以前,程序中使用的资源需要被明确地关闭,过程有点繁琐,如下所示:

  1. package com.qunar.lectures.tryResource;
  2. import java.io.*;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. /**
  6. * Created by xiaosi on 16-3-4.
  7. */
  8. public class TryResourceDemo {
  9.    // 获取资源数据
  10.    public static List<String> readLines(String resourcePath) {
  11.        String path = TryResourceDemo.class.getResource(resourcePath).getPath();
  12.        File file = new File(path);
  13.        if (!file.exists()) {
  14.            throw new RuntimeException("Can not find file + " + resourcePath);
  15.        }//if
  16.        if (!file.isFile()) {
  17.            throw new RuntimeException(resourcePath + " is not a regular file");
  18.        }//if
  19.        FileInputStream fis;
  20.        InputStreamReader isr;
  21.        BufferedReader br = null;
  22.        try {
  23.            fis = new FileInputStream(file);
  24.            isr = new InputStreamReader(fis, "UTF-8");
  25.            br = new BufferedReader(isr);
  26.            List<String> lines = new ArrayList<String>();
  27.            String line;
  28.            while ((line = br.readLine()) != null) {
  29.                lines.add(line);
  30.            }//while
  31.            return lines;
  32.        }
  33.        catch (IOException e) {
  34.            throw new RuntimeException("Read file failed , file=" + resourcePath, e);
  35.        }
  36.        finally {
  37.            if(br != null){
  38.                try {
  39.                    br.close();
  40.                } catch (IOException e) {
  41.                    e.printStackTrace();
  42.                }
  43.            }//if
  44.        }//finally
  45.    }
  46.    public static void main(String[] args) {
  47.        List<String> lines = readLines("/a.txt");
  48.        for(String line : lines){
  49.            System.out.println("line:" + line);
  50.        }//for
  51.    }
  52. }

假设try语句块抛出一个异常,然后finally语句块被执行。同样假设finally语句块也抛出了一个异常。那么哪个异常会根据调用栈往外传播?即使try语句块中抛出的异常与异常传播更相关,最终还是finally语句块中抛出的异常会根据调用栈向外传播。

  1. private static void printFileJava7() throws IOException {
  2.    try(FileInputStream input = new FileInputStream("file.txt")) {
  3.        int data = input.read();
  4.        while(data != -1){
  5.            System.out.print((char) data);
  6.            data = input.read();
  7.        }
  8.    }
  9. }

我们看到第一行:

  1. try(FileInputStream input = new FileInputStream("file.txt")) {

这就是try-with-resource 结构的用法。FileInputStream 类型变量就在try关键字后面的括号中声明并赋值。在这声明的变量我们可以在下面的代码中直接使用,即同一个作用域中。当try语句块运行结束时,FileInputStream会被自动关闭。这是因为FileInputStream 实现了java中的java.lang.AutoCloseable接口。所有实现了这个接口的类都可以在try-with-resources结构中使用。

当try-with-resources结构中抛出一个异常,同时FileInputStreami被关闭时(调用了其close方法)也抛出一个异常,try-with-resources结构中抛出的异常会向外传播,而FileInputStreami被关闭时抛出的异常被抑制了。这与文章开始处利用旧风格代码的例子(在finally语句块中关闭资源)相反。

在JDK7中只要实现了AutoCloseable或Closeable接口的类或接口,都可以使用try-with-resource来实现异常处理和资源关闭。

你可以在块中使用多个资源而且这些资源都能被自动地关闭:

  1. package com.qunar.lectures.tryResource;
  2. import java.io.*;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. /**
  6. * Created by xiaosi on 16-3-4.
  7. */
  8. public class TryResourceDemo {
  9.    // 获取资源数据
  10.    public static List<String> readLines(String resourcePath) {
  11.        String path = TryResourceDemo.class.getResource(resourcePath).getPath();
  12.        File file = new File(path);
  13.        if (!file.exists()) {
  14.            throw new RuntimeException("Can not find file + " + resourcePath);
  15.        }//if
  16.        if (!file.isFile()) {
  17.            throw new RuntimeException(resourcePath + " is not a regular file");
  18.        }//if
  19.        // try-with-resource方式 自动释放资源
  20.        try (FileInputStream fis = new FileInputStream(file);
  21.             InputStreamReader isr = new InputStreamReader(fis);
  22.                BufferedReader br = new BufferedReader(isr)){
  23.            List<String> lines = new ArrayList<String>();
  24.            String line;
  25.            while ((line = br.readLine()) != null) {
  26.                lines.add(line);
  27.            }//while
  28.            return lines;
  29.        }
  30.        catch (IOException e) {
  31.            throw new RuntimeException("Read file failed , file=" + resourcePath, e);
  32.        }
  33.    }
  34.    public static void main(String[] args) {
  35.        List<String> lines = readLines("/a.txt");
  36.        for(String line : lines){
  37.            System.out.println("line:" + line);
  38.        }//for
  39.    }
  40. }
时间: 2024-12-07 11:26:29

[Java开发之路](20)try-with-resource 异常声明的相关文章

7.[Java开发之路](5)异常

1. 异常分类 在Java程序设计语言中,异常对象都是派生于Throwable类的一个实例.其是如果Java中的异常类不能满足需求,用户可以创建自己的异常类. 下图是Java异常层次结构的一个简化示意图. 从图上可以看出,所有的异常都是继承于Throwable类,但是在下一层立即分解为两个分支:Error和Exception. (1)Error Error描述了Java运行时系统的内部错误和资源耗尽错误.应用程序不应该抛出这种类型的错误,如果出现了这样的内部错误,除了通告用户,并尽力使程序安全的

[Java开发之路](14)反射机制

1. Class类 普通对象构造方式: // 创建Book实例对象 Book book = new Book(); 对于Class的实例对象如何构造呢? Class的构造函数是私有的,只有JVM才能创建实例对象 // Class的构造函数是私有的,只有JVM才能创建Class实例对象 Class class1 = new Class(); // 错误 public final class Class<T> implements java.io.Serializable, java.lang.r

[Java开发之路](9)对象序列化与反序列化

1. 对象序列化 当你创建对象时.仅仅要你须要.它会一直存在,可是程序终止时,不管何时它都不会继续存在.虽然这样做是很有意义的,可是在某些情况下.假设程序不执行时扔能存在而且保存其信息,那将对我们很实用.这样,在下次程序执行时,该对象将被重建而且拥有的信息与程序上次执行时它所拥有的信息同样. 当然,我们也能够通过将信息写入文件或者数据库,可是假设能将一个对象声明为是"持久性"的,并为我们处理掉全部的细节,这将会显得十分方便. Java的序列化是将那些实现了Serializable接口的

[Java开发之路](7)RandomAccessFile类详解

RandomAccessFile适用于大小已知的记录组成的文件,提供的对文件访问,既可以读文件,也可以写文件,并且支持随机访问文件,可以访问文件的任意位置.文件中记录的大小不一定都相同,只要我们知道记录的大小和位置.但是该类仅限于操作文件. RandomAccessFile不属于InputStream和OutputStream继承层次结构中的一部分.除了实现DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口),它和

[Java开发之路](18)关于Class.getResource和ClassLoader.getResource的路径问题

Java中取资源时,经常用到Class.getResource和ClassLoader.getResource.昨天老师讲解题目时候,问我们为什么你们都是在文件前家上"/": String path = Resources.class.getResource("/a.txt").getPath(); 注:在Resources文件下创建了a.txt文件 我想我反正是试出来的,不使用"/"不行.为了正式解答心中的疑惑,我们正式来看看Resources

[Java开发之路](8)图说字符串的不变性

我们用下面一组图来说明Java的不变性. 1.声明一个字符串 String s = "abcd"; s存储了字符串对象的引用.下面图片中的箭头就表示这种存储引用. 2. 将一个字符串变量赋值给另外一个字符串变量 String s2 = s; s2变量存储了同样的引用值.所以,两个变量指向同一个字符串对象. 3. 合并字符串 s = s.concat("ef"); s现在存储的是新生成的字符串对象的引用. 4. 总结 一旦一个字符串在内存(堆)上创建,这个字符串就不会

[Java开发之路](6)File类的使用

1. 构造方法 构造方法 描写叙述 File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建一个新的文件实例. File(String parent , String child) 通过给定的父路径名字符串和子路径名字符串来创建一个新的文件实例. File(File parent , String child) 通过给定的父抽象路径对象和子路径名字符串来创建一个新的文件实例. File(URI uri) 通过给定的URI来创建一个新的文件实例 package c

[Java开发之路](11)SAX解析XML文档

1. 简介 Dom解析功能强大,可增删改查,操作时会将XML文档读到内存,因此适用于小文档: SAX解析是从头到尾逐行逐个元素解析,修改较为不便,但适用于只读的大文档: SAX采用事件驱动的方式解析XML.套用网友的解释:如同在电影院看电影一样,从头到尾看一遍,不能回退(Dom可来来回回读取),在看电影的过程中,每遇到一个情节,都会调用大脑去接收处理这些信息.SAX也是相同的原理,每遇到一个元素节点,都会调用相应的方法来处理.在SAX的解析过程中,读取到文档开头.文档结尾,元素的开头和元素结尾都

[Java开发之路](23)装箱与拆箱

1. 简单介绍 大家对基本数据类型都很熟悉.比如 int.float.double.boolean.char 等.基本数据类型是不具备对象的特性,比方基本类型不能调用方法.功能简单. ..,为了让基本数据类型也具备对象的特性, Java 为每一个基本数据类型都提供了一个包装类,这样我们就能够像操作对象那样来操作基本数据类型. 对象包装类是不变的,即一旦构造了包装类,就不同意更改包装在当中的值. 同一时候,对象包装类还是final,因此不能定义它们的子类. 如果想定义一个整型数组列表,而尖括号里的