今天,我们有一个主题与我们上周讨论的主题完全一致。 上周,主题是定型剂和清洁剂。 这些的常见用途之一是清理资源。 在此博客文章中,我们将进一步详细介绍上一篇文章末尾所暗示的更好方法。
由于种种原因,有许多资源在使用后需要手动关闭。 这通常是通过使用关 method on the object. We of course don't want to leak resources or leave items in a half handled state. This being the case we may consider putting the 关 method in a 最后块。 例如:
static List<Object> getDbValues() {
EntityManager em = getEntityManager();
try {
return em.createNativeQuery("SELECT * FROM myTable").getResultsList();
} finally {
em.close();
}
}
这样就可以了,看起来还不错。 随着我们添加更多资源,它的确变得更加混乱和容易出错。
static List<Object> getDbValues() {
OutputStream output = getOutputStream();
InputStream input = getInputstream();
try {
try {
// do work
} finally {
input.close();
}
} finally {
output.close();
}
}
这开始变得越来越粗糙,难以遵循。 我什至做对了吗? 我不相信。 很容易搞砸。 作者甚至承认,多年来他的一本书中都把这种模式弄乱了,没有人意识到。 即使使用正确的代码,错误处理的细微之处也无法得到很好的处理。 异常可能会相互覆盖,我们可能会在发生的堆栈跟踪中丢失有价值的信息。 您可以编写代码来处理此问题,但是它既复杂又丑陋,因此没人能这样写。
因此,在Java 7中,我们得到了更好的答案,尝试资源。 有了这个构造,任何实现的类自动关闭可以用Java处理它的关闭。 因此上面的例子看起来像:
try(InputStream input = new FileInputStream("file");
OutputStream output = new FileOutputStream("other")) {
// do work
}
这要简单得多。 它处理的内容比上一个示例还要多。 这实际上不是代码保留的方式。 上面的代码被编译器转换为更加冗长的结果。 让我们来看看:
InputStream input = new FileInputStream("file");
Throwable var2 = null;
try {
OutputStream output = new FileOutputStream("other");
Throwable var4 = null;
try {
//do work
} catch (Throwable var27) {
var4 = var27;
throw var27;
} finally {
if (output != null) {
if (var4 != null) {
try {
output.close();
} catch (Throwable var26) {
var4.addSuppressed(var26);
}
} else {
output.close();
}
}
}
} catch (Throwable var29) {
var2 = var29;
throw var29;
} finally {
if (input != null) {
if (var2 != null) {
try {
input.close();
} catch (Throwable var25) {
var2.addSuppressed(var25);
}
} else {
input.close();
}
}
}
哇! 那变得非常激烈。 但是,如果您仔细分析它,您会发现它正在做我们希望的工作,同时可以更彻底地处理异常。
Final thought. In a previous post I mentioned the tool Lombok. I very much think this is a good tool. Inside the bag of tricks of Lombok there is an annotation @Cleanup
. It looks like it will do something very similar to the above. So what makes these two different. While it is correct that they do similar things they do have a slight different. The main difference is that @Cleanup
simply writes the try-finally combinations like we did above but doesn't do any magic handling the exception handling. So while @Cleanup
does give us the safety of a finally block we do lose the specialized exception handling.
所以你有它。 使用try-with-resources。 更简单,更清洁,更安全,这确实是一个我看不到太多缺点的地方。
from: https://dev.to//kylec32/effective-java-tuesday-prefer-try-with-resources-2om9