JDK1.7之前
在JDK1.7之前要確保外部資源關閉一般使用finally,如下
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(new File("user.csv"));
System.out.println(inputStream.read());
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
try-with-resource
在JDK1.7及之後對於實現了AutoCloseable接口的對象可以使用try-with-resource語法,該語法會確保外部資源的close方法被調用。如下:
try (FileInputStream inputStream = new FileInputStream(new File("test"))) {
System.out.println(inputStream.read());
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
原理
JDK1.7實現了的一個語法糖,其實對JVM虛擬機而言,它看到的依然是之前的寫法,反編譯後的結果:
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);
這叫異常抑制。當對外部資源進行處理和關閉外部資源時都遇到異常,catch到的將會是對外部資源進行處理時遭遇的異常,關閉資源的異常將被“抑制”(但不是丟棄),通過異常的getSuppressed方法,可以提取出被抑制的異常。