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

Mis*_*ble 57 java try-with-resources

参考我的问题java.util.concurrent.locks.Lock的AutoCloseable包装中的任何风险?,我想知道为什么trh try-with-resource需要一个命名的局部变量.

我目前的用法如下:

try (AutoCloseableReentrantReadWiteLock.Lock l = _lock.writeLock()) {
    // do something
}        
Run Code Online (Sandbox Code Playgroud)

该变量l在try块内未使用,仅污染命名空间.从我记忆中的类比C# using语句不需要本地命名变量.

是否有任何理由无法支持以下内容,并且在try块结束时关闭了一个匿名局部变量?

try (_lock.writeLock()) {
    // do something
}        
Run Code Online (Sandbox Code Playgroud)

Zer*_*ro3 13

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

回到JDK 7,我们从一个try-with-resources构造开始,就像允许一般表达式用于资源,包括方法调用.但是,早期审查草案(http://jcp.org/aboutJava/communityprocess/edr/jsr334/index.html)发现的专家组认为

"未来可能会发生变化[尝试资源状态"]正在放弃对指定为一般表达式的资源的支持.通过允许将一般表达式用作资源,产生了非常重要的规范和实现复杂性.可能是标识符或者PrimaryNoNewArray可能就足够了.即使是仅仅允许标识符的更严格的限制也可以提供几乎所有允许完全表达(强制声明新资源变量)的附加效用,并且边缘实现要低得多.规范影响."

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

  • java9仍然不支持OP的情况. (8认同)

Zho*_*gYu 8

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

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

展望未来,尝试资源可能会脱离时尚,取而代之的是lambda.例如

lock.withLock( ()->{ execute-while-holding-the-lock; } );
Run Code Online (Sandbox Code Playgroud)

  • 恕我直言,这是对lambdas的滥用.有0个好处,它使代码更难阅读.不要这样做. (6认同)

Ale*_*exR 0

我认为无法使用局部变量是 try-with-resource 的触发因素。

在 java 1.7 之前,您必须编写如下内容:

InputStream in = null;
try {
    in = ....;
} finally {
    if (in != null) {
        in.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

这里有两个缺点:

  1. finally块很烦人,并且对于每个关闭资源都必须是空安全的
  2. 我们必须在块外声明资源才能在finally块中访问它们。因此,我们扩大了变量可访问的范围,这是不好的做法。

Try-with-resource 语法解决了这两个问题:

  1. finally根本不需要块。
  2. 资源变量仍然try只能在块中访问,即在应该知道的地方。

这就是为什么可关闭资源必须是本地的。否则,try-with-resource 语法的主要缺点之一是“禁用”。

  • 您已经提供了一个在 try-with-resources 中“允许”声明的充分理由。OP 问为什么它是*必需的*。 (9认同)
  • 您可以编辑您的答案吗?以目前的形式,它不能回答我的问题 (3认同)