为什么 try-with-resource 需要一个局部变量?

2022-08-31 14:36:05

关于我的问题 Java.util.concurrent.locks.Lock 的 AutoCloseable 包装器中的任何风险,我想知道为什么 try-with-resource-statement 需要一个命名的局部变量。

我目前的用法如下:

try (AutoCloseableReentrantReadWiteLock.Lock l = _lock.writeLock()) {
    // do something
}        

该变量在 try 块中未使用,只会污染命名空间。据我所知,类似的C#-语句不需要局部命名变量。lusing

是否有任何原因不支持以下内容,并在 try 块结束时关闭一个匿名局部变量?

try (_lock.writeLock()) {
    // do something
}        

答案 1

@McDowell的评论中的链接揭示了Joe Darcy在博客文章评论中的正确答案,他领导了Java技术规范,该规范引入了try-with-resources声明:

早在 JDK 7 中,我们从一个 try-with-resources 构造开始,该构造允许将通用表达式用于资源,包括方法调用。然而,专家组在早期审查草案(http://jcp.org/aboutJava/communityprocess/edr/jsr334/index.html)中发现

“将来可能的变化(对 try-with-resources statemenbt)是放弃对要指定为通用表达式的资源的支持。非平凡的规范和实现复杂性源于允许将通用表达式用作资源。一个受限制的表达式可以是标识符或 PrimaryNoNewArray 可能就足够了。即使是更严格的限制,即只允许一个标识符,也可能提供几乎所有的额外效用,允许一个完整的表达式(而不是强制声明一个新的资源变量),而边际实现和规范的影响要小得多。

到 JDK 7 结束时,我们想要的是资源的全新变量声明或现有的最终/有效最终变量。我们只有时间在7中提供前者;在9中,我们也提供后者。


答案 2

在他们正在考虑的用例中,大多数人需要访问块内的资源,例如,打开文件 - 读/写文件 - 关闭文件。如果他们认为有很多用例中局部变量未被使用,他们就不会做出这个设计决定。

至于为什么Lock不能自动关闭,我认为Doug Lea不太关心语法问题,他专注于解决难题。其他人总是可以在他的实用程序之上添加语法糖。

展望未来,尝试资源可能会过时,取而代之的是lambda。例如

lock.withLock( ()->{ execute-while-holding-the-lock; } );

推荐