我有以下代码,我正在通过强化运行。为什么它被标记为糟糕的错误处理,最后扔进去?
private String getResourceContent(String fileName) throws IOException {
try (InputStream resource = ErrorResource.classLoader.getResourceAsStream(fileName)) {
return new String(resource.readAllBytes(), StandardCharsets.UTF_8);
} catch (NullPointerException n) {
throw new ErrorDescriptorException(
String.format("Error loading Error description data from Resource file [%s].", fileName), n);
}
}
最佳答案
解释
这在官方文档中有很好的解释(参见 Poor Error Handling: Throw Inside Finally )。让我快速引用重要部分:
Using a
throw
statement inside afinally
block breaks the logical progression through the try-catch-finally.In Java, finally blocks are always executed after their corresponding try-catch blocks and are often used to free allocated resources, such as file handles or database cursors. Throwing an exception in a finally block can bypass critical cleanup code since normal program execution will be disrupted.
因此您可以通过这样做轻松绕过清理代码,从而导致资源泄漏。
虽然在您的代码中不直接可见,但您实际上有一个隐藏 finally
block ,因为您正在使用 try-with-resources 自动在 finally block 中关闭资源。
另见 Throwing an exception inside finally已经讨论过了。
例子
这是官方文档中的一个例子:
public void processTransaction(Connection conn) throws FileNotFoundException {
FileInputStream fis = null;
Statement stmt = null;
try {
stmt = conn.createStatement();
fis = new FileInputStream("badFile.txt");
...
} catch (FileNotFoundException fe) {
log("File not found.");
} catch (SQLException se) {
// handle error
} finally {
if (fis == null) {
// This bypasses cleanup code
throw new FileNotFoundException();
}
if (stmt != null) {
try {
// Not executed if the exception is thrown
stmt.close();
}
catch (SQLException e) {
log(e);
}
}
}
}
当 FileNotFoundException
被抛出时,对 stmt.close()
的调用被绕过。
注意事项
为什么要使用 NullPointerException
而不是基本的 if-else 检查 null
?很少有有效的理由来捕获 NullPointerException
。只是做:
try (InputStream resource = ErrorResource.classLoader.getResourceAsStream(fileName)) {
if (resource == null) {
// TODO Throw your exception here
}
return new String(resource.readAllBytes(), StandardCharsets.UTF_8);
}
通过告知无法找到资源的确切原因,也可能有助于改进错误消息。
关于Java:糟糕的错误处理,Throw inside Finally,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57673658/