简介+优势分析
- try-with-resource借鉴链接(建议先看看,内容十分详实,我做了一点点补充) https://www.cnblogs.com/itZhy/p/7636615.html
- IOUtils出处 https://blog.csdn.net/zmx729618/article/details/51888938/
举个小栗子
pom简单依赖
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
运行1
public static void main(String[] args) {
try (FileInputStream inputStream = new FileInputStream(new File("test.txt"))) {
// 读取到控制台
System.out.println(inputStream.read());
// 关闭输入流 , 该方法需要上面的pom依赖
IOUtils.closeQuietly( inputStream );
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
结果1
Exception in thread "main" java.lang.RuntimeException: test.txt (系统找不到指定的文件。)
at Main.main(Main.java:16)
Caused by: java.io.FileNotFoundException: test.txt (系统找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at Main.main(Main.java:10)
: 可以发现 IOUtils.closeQuietly( inputStream );
关闭流错误的信息没有往外抛出来.这就是因为closeQuietly方法进行了空指针判断! 不是异常抑制!
public static void closeQuietly(Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (IOException var2) {
;
}
}
同时存在异常抑制
看一眼反编译后的代码
public class Main {
public Main() {
}
public static void main(String[] args) {
try {
FileInputStream inputStream = new FileInputStream(new File("test.txt"));
Throwable var2 = null;
try {
System.out.println(inputStream.read());
IOUtils.closeQuietly(inputStream);
} 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);
- 这是try-with-resource语法涉及的另外一个知识点,叫做异常抑制。当对外部资源进行处理(例如读或写)时,如果遭遇了异常,且在随后的关闭外部资源过程中,又遭遇了异常,那么你catch到的将会是对外部资源进行处理时遭遇的异常,关闭资源时遭遇的异常将被“抑制”但不是丢弃,通过异常的getSuppressed方法,可以提取出被抑制的异常。
- try-with-resource时,如果对外部资源的处理和对外部资源的关闭均遭遇了异常,“关闭异常”将被抑制,“处理异常”将被抛出,但“关闭异常”并没有丢失,而是存放在“处理异常”的被抑制的异常列表中。
释放异常抑制
加点pom
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
<!-- log -->
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
加点代码, 使用e.getSuppressed(); 获取到被压抑的没能抛出的异常
@Slf4j
public class Main {
public static void main(String[] args) {
try (FileInputStream inputStream = new FileInputStream(new File("test.txt"))) {
// 读取到控制台
System.out.println(inputStream.read());
// 关闭输入流
IOUtils.closeQuietly( inputStream );
} catch (IOException e) {
Throwable[] suppressed = e.getSuppressed();
for (Throwable throwable : suppressed) {
log.error("", throwable);
}
throw new RuntimeException(e.getMessage(), e);
}
}
}
造一组样例
对外部资源的处理和对外部资源的关闭均遭遇了异常, 太难了, 造不出来.....................
如果你可以的, 麻烦在下面贴一下`英雄帖`!
注意编译版本的问题, 至少需要JDK5, 请在pom中指定jdk编译版本
pom中指定即可
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>