Java的AutoCloseable
功能“重用” try / catch语义:
try (Stream x = ...) {
// work with x
}
// x is out of scope and was auto-closed
我很好奇为什么他们没有为此新功能引入新的语义。 try
表示您希望主体在某一点或另一点抛出异常(或可能会抛出异常)。对我而言,这与“实例化该资源并在完成后将其关闭”大不相同。这与处理异常没有任何关系。为什么不这样呢?
with (Stream x = ...) { ... }
using (Stream x = ...) { ... } // I know, C# syntax
我不想引起争论,我想知道Java团队决定为此功能重新使用try
的原因。
答案 0 :(得分:3)
Java始终尽力向后兼容。这是当今语言几乎所有奇怪或不幸的方面的原因。 It's happened a handful of times,但引入诸如with
或using
之类的新关键字并不是要轻率的决定。如果他们引入了新的关键字using
,则诸如int using = 0
之类的旧代码将无法针对Java *的最新版本进行编译。
try-with-resources来减少以下常见模式的冗长性:
SomeResource resource;
try {
resource = new Resource();
resource.foo();
}
//optional catch
finally {
if (resource != null) resource.close();
}
因为try
之前已经涉及到,所以向try
添加附加功能是合乎逻辑的。
*有趣的是,进行了类似的讨论over Java 10's var
,它实际上不是关键字,而是“保留类型名称”(因此语义略有不同):
风险:源代码不兼容(可能有人使用var作为类型 名称。)
答案 1 :(得分:2)
问题部分是关于Java语言的设计选择的。由于问题的性质,此答案只是问题的部分答案。
try-with-resources
不会重用try
-catch
概念,而会重用try
-finally
概念。尽管很少见,try-finally
有其用途。例如,您可以代替显式捕获异常并重新引发它,而只需在finally
块中进行一些清理。 1
AutoCloseable
resources的性质非常适合此用例:打开AutoCloseable
资源,执行任何操作,最后不管如何关闭它。
有人可能会争辩说,通过try
启动此过程似乎是人为的。但是,这是语言承诺的设计决定,因此不值得争论。如果我不得不猜测,我会选择Michael's line of argumentation,说他们不想引入新的关键字来保持向后兼容。
1 我知道pointed out by @Radiodef是try-with-resources
will be translated to a try-catch-finally
的事实。但是,从我的角度来看,这是一个实现细节,也是一个指定行为的工具。理解语义并不是必需的。