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 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);}//ifif (!file.isFile()) {throw new RuntimeException(resourcePath + " is not a regular file");}//ifFileInputStream fis;InputStreamReader isr;BufferedReader br = null;try {fis = new FileInputStream(file);isr = new InputStreamReader(fis, "UTF-8");br = new BufferedReader(isr);List lines = new ArrayList(); String line;while ((line = br.readLine()) != null) {lines.add(line);}//whilereturn 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 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 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);}//ifif (!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 lines = new ArrayList(); String line;while ((line = br.readLine()) != null) {lines.add(line);}//whilereturn lines;}catch (IOException e) {throw new RuntimeException("Read file failed , file=" + resourcePath, e);}}public static void main(String[] args) {List lines = readLines("/a.txt"); for(String line : lines){System.out.println("line:" + line);}//for}}