一、背景
JDK8之前關閉資源
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
JDK8中關閉資源
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
二、以上兩種方式依然存在問題
http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
try...catch...塊中如果出現異常,在執行finally過程中如果還出現異常,會影響原異常的拋出,此種現象叫做異常壓制。
三、Guava Closer
解決上述問題,使得原始異常不被壓制、影響分析問題
package com.mzj.guava.io.closer;
import com.google.common.io.Closer;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class CloserTest {
/**
* Guava Closer解決異常被壓制問題:好處是:不會漏掉異常、影響分析問題
*
* 此方法僅僅用於演示,不能運行,main方法中代碼可以運行
*
* @param args
* @throws IOException
*/
@Test
public void test(String[] args) throws IOException {
Closer closer = Closer.create();
try {
//將Closeable註冊到Closer中,讓其幫我們close
BufferedReader br = closer.register(new BufferedReader(new FileReader("E:\\01.study\\03.google guava\\wamgwenjun\\other\\googleguava\\src\\main\\resources\\io\\source.txt")));
br.readLine();
} catch (IOException e) {
throw closer.rethrow(e);//拋出原始異常
} finally {
closer.close();//調用register的Closeable的close();如果close過程出現異常則進行異常傳遞(追加):原始異常+finally執行異常統一封裝、全部拋出
}
}
//===================下面所有代碼演示瞭如果不使用Guava Closer,異常被壓制的產生過程,如果解決(下面的解決過程就是Guava Closer實現)===================
/**
* 用於測試異常拋出、catch語句塊、finally語句塊執行順序
*/
@Test(expected = RuntimeException.class)
public void testTryCatchFinally() {
try {
System.out.println("work area");
throw new IllegalArgumentException();
} catch (Exception e) {
System.out.println("exception area");
} finally {
System.out.println("finally area");
}
}
/**
* 演示try...finally...機制,如果在正常語句拋出異常後執行finally過程再拋異常就會壓制原異常的問題
*
* 執行:只看到異常2,異常1被壓制了。。。。
*/
// public static void main(String[] args) {
// try {
// throw new RuntimeException("1");
// } catch (Exception e) {
// throw e;
// } finally {
// //模擬執行close時拋出異常
// throw new RuntimeException("2");
// }
// }
/**
* 解決上述問題
* <p>
* 執行:看到1,2兩個異常
* <p>
* 這種方式就是Guava Closer所解決的問題
*/
public static void main(String[] args) {
Throwable t = null;
try {
throw new RuntimeException("1");
} catch (Exception e) {
t = e;
throw e;
} finally {
RuntimeException runtimeException = new RuntimeException("2");
runtimeException.addSuppressed(t);//異常傳遞(追加)
throw runtimeException;
}
}
}