2013-05-16 39 views
49

参考我的问题Any risk in a AutoCloseable wrapper for java.util.concurrent.locks.Lock?,我想知道为什么trh try-with-resource需要命名为局部变量。为什么try-with-resource需要一个局部变量?

我现在的用法如下:

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

变量l是try块内未使用的,只有污染的命名空间。从我所记得的类似的C#using语句不需要本地命名变量。

是否有任何原因,以下情况可能不被支持,并且在try块结束时关闭一个匿名局部变量?

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

这是[在Java 9中解决](https://blogs.oracle.com/darcy/entry/concise_twr_jdk9)。参见[JDK-8068949](https://bugs.openjdk.java.net/browse/JDK-8068948)。 – McDowell

+2

@McDowell Java 9通过允许使用_existing_有效的最终变量来解决当前需要定义_new_变量的行为。从链接中不会显示Java 9将支持可自动关闭的资源_而不会显示标识符_。 ([在这里讨论。](http://mail.openjdk.java.net/pipermail/core-libs-dev/2015-January/030864.html)) –

回答

1

我认为无法使用本地变量是试用资源的触发器。

此前的Java 1.7,你必须写这样的事情:

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

有2个缺点在这里:

  1. finally块是讨厌,必须是空安全的每个收盘资源
  2. 我们必须声明区块外的资源只能在finally区块中访问它们。因此我们扩大了变量可访问的范围,这是不好的做法。

尝试 - 与资源语法解决了两个问题:是不是需要在所有

  1. finally块。
  2. 资源变量只能在try块中保持可访问,即应该知道的地方。

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

+7

你已经提供了一个很好的理由* allow *声明试用资源。 OP询问为什么它是*必需的*。 –

+0

主要动机显然是避免了大量的样板,并为程序员提供了现成的解决方案,以解决相当复杂和细微的问题。我认为范围问题是最大的。整个故事的10%。 –

+0

对不起,我意识到[ResourceSpecification](http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3)块引入了一个局部变量,我的问题是为什么它必须命名。 –

8

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

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

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

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

为lamda使用+1。其余的是投机性的。虽然可能是正确的,但我更感兴趣的是,如果有理由不能做到。 –

+0

确定它可以完成,这只是更多的工作,他们并不认为这是值得的。 – ZhongYu

+5

恕我直言,这是滥用lambdas。有0个好处,并且使代码更难阅读。不要这样做。 –

4

尽管我希望不是这样,它背后的理由是,在try-与资源旨在严格地必须处理关于该项目的操作。它需要一个命名变量,因为它希望当你在块内时你会用这个变量做一些事情。我想这就像编译器说的:“如果你不打算真正使用这个资源,为什么你要用资源尝试?”

现在你和我完全清楚我们不想真正使用这个资源:我们只是想确保它在我们完成后关闭,所以我们没有开发人员去锁定系统。但是像很多事情一样,他们不得不做出设计决策并占据少数,我们没有得到这个功能。

+5

我*使用资源 - 因为它在'()'和'close()' –

+0

中的副作用,但是你并没有在块中使用它,这是try-with-resources的主要用例。我也觉得很沮丧,但事实就是如此。您可以通过'导入静态'锁定您的Lock类来节省自己的一些房地产。 – corsiKa

+0

有许多理由不在块中明确使用资源,例如它可能是锁;或者保存在一个ThreadLocal中。 –

11

由@McDowell评论的链接揭示了由乔达西a blog post comment正确答案谁领导the Java Technology Specification引入的尝试,与资源声明:

早在JDK 7,我们开始尝试-with-resources结构,如 ,它允许使用一般表达式作为资源, 包括方法调用。然而,由早期 审查 (http://jcp.org/aboutJava/communityprocess/edr/jsr334/index.html)草案

“一个可能的发展变化[去尝试,用资源statemenbt]发现专家组是 对于要指定的资源作为一般 下探支撑由于允许使用一般表达式作为资源,所以出现非平凡的规范和实施复杂性 可能是标识符或 PrimaryNoNewArray可能就足够了,即使更严格的 限制只允许一个标识符,所有额外的 实用程序允许一个完整的表达式通过强制声明 一个新的资源变量)在一个更低的边际执行和 规范的影响。“

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

+4

java9仍然不支持OP的情况。 – ZhongYu

相关问题