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

引用我的问题java.util.concurrent.locks.Lock的AutoCloseable包装中的任何风险? ,我想知道为什么TRH try-with-resource需要一个命名的局部variables。

我目前的用法如下:

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

variablesl在try块内未被使用,只会污染名字空间。 从我记得的类似的C# using语句不需要本地命名variables。

是否有任何原因,以下不能被支持,与一个匿名的本地variables,在try块结束时closures?

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

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

回到JDK 7,我们从一个try-with-resources结构开始,就像允许一般expression式被用于资源一样,包括一个方法调用。 然而,早期草案审查发现的专家组( http://jcp.org/aboutJava/communityprocess/edr/jsr334/index.html

“对资源尝试状态的未来可能的变化是放弃对作为通用expression式的资源的支持。通过允许将通用expression式用作资源,非平凡的规范和实现的复杂性产生了。可能是一个标识符,或者PrimaryNoNewArray就足够了,即使是允许一个标识符的更严格的限制也可以提供几乎所有的附加效用,允许一个完整的expression式(通过强制声明一个新的资源variables)在一个更低的边际实现上规范影响“。

到JDK 7结束时,我们想要的是一个新的资源variables声明或现有的最终/有效的最终variables。 我们只有7点时间提供给前者。 在9,我们也提供后者。

在他们正在考虑的用例中,大多数需要访问块内的资源,例如打开文件 – 读/写文件 – closures文件。 如果他们认为在局部variables未被使用的情况下有很多用例,他们就不会做出这个devise决定。

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

outlook未来,尝试与资源可能会失去时尚,取而代之的是lambda。 例如

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

尽pipe我不希望这样做,但其背后的基本原理是,试用资源仅限于必须处理的物品的操作。 它需要一个命名的variables,因为它希望当你在块内部的时候你会用这个variables做一些事情。 我想这就像编译器说:“如果你不打算真正使用这个资源,你为什么要做一个试用资源?

现在我们已经很清楚地知道,我们并不想真正使用这个资源,相反,当我们完成这个工作时,我们只是想确保它是closures的,所以我们没有开发人员来locking系统。 但是像很多事情一样,他们不得不做出devise决策并且处于less数,我们没有得到这个function。

我认为无法使用本地variables是触发尝试资源。

在Java 1.7之前,你必须写下这样的东西:

 InputStream in = null; try { in = ....; } finally { if (in != null) { in.close(); } } 

这里有两个缺点:

  1. finally块是烦人的,必须为每个closures资源无效
  2. 我们必须在块之外声明资源才能在finally块中访问它们。 因此,我们扩大了variables可访问的范围,这是不好的做法。

试用资源语法解决了这两个问题:

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

这就是为什么可closures的资源必须是本地的。 否则,尝试资源语法的一个主要缺点是“禁用”。