3 回答
TA贡献1876条经验 获得超6个赞
解释
让我快速引用重要部分:
throw
在块内使用语句finally
会破坏 try-catch-finally 的逻辑进程。在 Java 中,finally 块始终在相应的 try-catch 块之后执行,并且通常用于释放分配的资源,例如文件句柄或数据库游标。在 finally 块中抛出异常可以绕过关键的清理代码,因为正常的程序执行将被中断。
因此,您可以通过这样做轻松绕过清理代码,从而导致资源泄漏。
虽然在代码中不直接可见,但实际上有一个隐藏 finally
块,因为您使用的是try-with-resources,它会自动关闭 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);
}
}
}
}
抛出时绕过stmt.close()
对的调用。FileNotFoundException
笔记
为什么要检查是否null
使用 aNullPointerException
而不是基本的if-else?很少有正当理由去抓捕NullPointerException
。做就是了:
try (InputStream resource = ErrorResource.classLoader.getResourceAsStream(fileName)) {
if (resource == null) {
// TODO Throw your exception here
}
return new String(resource.readAllBytes(), StandardCharsets.UTF_8);
}
通过告知无法找到资源的确切原因,它也可能有助于改进错误消息。
TA贡献1872条经验 获得超3个赞
考虑以下代码,它大致基于您的代码:
String throwing(InputStream inputStream) throws IOException {
try (InputStream resource = inputStream) {
return "good";
} catch (NullPointerException n) {
return "bad";
}
}
你看,这里没有抛出异常。尽管如此,你还是无法移除这个throws IOException部分——那是怎么回事?好吧,InputStream#close()可以抛出它,它将位于finallytry-with-resources 语句创建的隐式块中。我想您对此无能为力,它看起来像是 Fortify 误报。
TA贡献1834条经验 获得超8个赞
除了工具中的误导性消息之外,您的代码中实际上存在糟糕的错误处理,原因有多种:
捕捉 NPE 是非常糟糕的做法。要么它是一个错误(某些东西是 null 并且不应该),要么你的代码缺少检查
if (whatever == null)
和相应的代码来处理这种预期情况假设这个 NPE 具有您在新 Exception 中表达的确切含义,只是猜测
换句话说:在没有更多信息的情况下,不清楚您的工具到底抱怨什么。但是:不需要工具来理解:这是糟糕的错误处理。
除此之外,此类工具通常会提供有关其警告的某种信息。意思是:该警告可能带有一个“错误 ID”,您应该能够在您的工具文档中查找该“错误 ID”以获得进一步的解释。
添加回答
举报