Try-with-resources是java7中一個新的異常處理機制,它能夠很容易地關閉在try-catch語句塊中使用的資源。
在java7以前,程序中使用的資源需要被明確地關閉,過程有點繁瑣,如下所示:
~~~
package com.qunar.lectures.tryResource;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* Created by xiaosi on 16-3-4.
*/
public class TryResourceDemo {
? ?// 獲取資源數據
? ?public static List<String> readLines(String resourcePath) {
? ? ? ?String path = TryResourceDemo.class.getResource(resourcePath).getPath();
? ? ? ?File file = new File(path);
? ? ? ?if (!file.exists()) {
? ? ? ? ? ?throw new RuntimeException("Can not find file + " + resourcePath);
? ? ? ?}//if
? ? ? ?if (!file.isFile()) {
? ? ? ? ? ?throw new RuntimeException(resourcePath + " is not a regular file");
? ? ? ?}//if
? ? ? ?FileInputStream fis;
? ? ? ?InputStreamReader isr;
? ? ? ?BufferedReader br = null;
? ? ? ?try {
? ? ? ? ? ?fis = new FileInputStream(file);
? ? ? ? ? ?isr = new InputStreamReader(fis, "UTF-8");
? ? ? ? ? ?br = new BufferedReader(isr);
? ? ? ? ? ?List<String> lines = new ArrayList<String>();
? ? ? ? ? ?String line;
? ? ? ? ? ?while ((line = br.readLine()) != null) {
? ? ? ? ? ? ? ?lines.add(line);
? ? ? ? ? ?}//while
? ? ? ? ? ?return lines;
? ? ? ?}
? ? ? ?catch (IOException e) {
? ? ? ? ? ?throw new RuntimeException("Read file failed , file=" + resourcePath, e);
? ? ? ?}
? ? ? ?finally {
? ? ? ? ? ?if(br != null){
? ? ? ? ? ? ? ?try {
? ? ? ? ? ? ? ? ? ?br.close();
? ? ? ? ? ? ? ?} catch (IOException e) {
? ? ? ? ? ? ? ? ? ?e.printStackTrace();
? ? ? ? ? ? ? ?}
? ? ? ? ? ?}//if
? ? ? ?}//finally
? ?}
? ?public static void main(String[] args) {
? ? ? ?List<String> lines = readLines("/a.txt");
? ? ? ?for(String line : lines){
? ? ? ? ? ?System.out.println("line:" + line);
? ? ? ?}//for
? ?}
}
~~~
假設try語句塊拋出一個異常,然后finally語句塊被執行。同樣假設finally語句塊也拋出了一個異常。那么哪個異常會根據調用棧往外傳播?即使try語句塊中拋出的異常與異常傳播更相關,最終還是finally語句塊中拋出的異常會根據調用棧向外傳播。
~~~
private static void printFileJava7() throws IOException {
? ?try(FileInputStream input = new FileInputStream("file.txt")) {
? ? ? ?int data = input.read();
? ? ? ?while(data != -1){
? ? ? ? ? ?System.out.print((char) data);
? ? ? ? ? ?data = input.read();
? ? ? ?}
? ?}
}
~~~
我們看到第一行:
~~~
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來實現異常處理和資源關閉。
你可以在塊中使用多個資源而且這些資源都能被自動地關閉:
~~~
package com.qunar.lectures.tryResource;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* Created by xiaosi on 16-3-4.
*/
public class TryResourceDemo {
? ?// 獲取資源數據
? ?public static List<String> readLines(String resourcePath) {
? ? ? ?String path = TryResourceDemo.class.getResource(resourcePath).getPath();
? ? ? ?File file = new File(path);
? ? ? ?if (!file.exists()) {
? ? ? ? ? ?throw new RuntimeException("Can not find file + " + resourcePath);
? ? ? ?}//if
? ? ? ?if (!file.isFile()) {
? ? ? ? ? ?throw new RuntimeException(resourcePath + " is not a regular file");
? ? ? ?}//if
? ? ? ?// try-with-resource方式 自動釋放資源
? ? ? ?try (FileInputStream fis = new FileInputStream(file);
? ? ? ? ? ? InputStreamReader isr = new InputStreamReader(fis);
? ? ? ? ? ? ? ?BufferedReader br = new BufferedReader(isr)){
? ? ? ? ? ?List<String> lines = new ArrayList<String>();
? ? ? ? ? ?String line;
? ? ? ? ? ?while ((line = br.readLine()) != null) {
? ? ? ? ? ? ? ?lines.add(line);
? ? ? ? ? ?}//while
? ? ? ? ? ?return lines;
? ? ? ?}
? ? ? ?catch (IOException e) {
? ? ? ? ? ?throw new RuntimeException("Read file failed , file=" + resourcePath, e);
? ? ? ?}
? ?}
? ?public static void main(String[] args) {
? ? ? ?List<String> lines = readLines("/a.txt");
? ? ? ?for(String line : lines){
? ? ? ? ? ?System.out.println("line:" + line);
? ? ? ?}//for
? ?}
}
~~~
- 前言
- [Hibernate開發之路](1)Hibernate配置
- [Hibernate開發之路](2)Hibernate問題
- [Hibernate開發之路](3)基礎配置
- [Hibernate開發之路](4)ID生成策略
- [Hibernate開發之路](5)聯合主鍵
- [設計模式實踐之路](1)單例模式
- [Java]UDP通信的簡單例子
- [Java]套接字地址InetAddress講解
- [Java開發之路](1)final關鍵字
- [Java開發之路](2)Java字符串
- [Java開發之路](3)Java常用類
- [Java開發之路](4)String、StringBuffer與StringBuilder詳解
- [Java開發之路](5)異常詳解
- [Java開發之路](6)File類的使用
- [Java開發之路](7)RandomAccessFile類詳解
- [Java開發之路](8)輸入流和輸出流
- [Java開發之路](9)對象序列化與反序列化
- [Java開發之路](10)DOM解析XML文檔
- [Java開發之路](11)SAX解析XML文檔
- [Java開發之路](12)JDOM和DOM4J解析XML文檔
- [Java開發之路](14)反射機制
- [Java開發之路](15)注解
- [Java開發之路](16)學習log4j日志
- [Java開發之路](18)關于Class.getResource和ClassLoader.getResource的路徑問題
- [Java開發之路](19)Long緩存問題
- [Java開發之路](20)try-with-resource 異常聲明
- [Java開發之路](21)Comparator與Comparable
- [Java]Java工程師成神之路
- [細說Java](1)圖說字符串的不變性
- [細說Java](2)Java中字符串為什么是不可變的
- [細說Java](3)創建字符串是使用&quot; &quot;還是構造函數?