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

时间:2013-05-16 13:30:50

标签: java try-with-resources

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

我目前的用法如下:

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

变量l在try块中未使用,仅污染命名空间。根据我的记忆,类似的C# using语句不需要本地命名变量。

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

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

4 个答案:

答案 0 :(得分:11)

@McDowell评论中的链接在a blog post comment中显示了Joe Darcy的正确答案,他带领the Java Technology Specification引入了try-with-resources语句:

  

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

     

“可能的未来变化[尝试资源状态]是   删除对指定为常规资源的支持   表达。非平凡的规范和实现的复杂性   允许将一般表达式用作资源。一个   限制表达式,可以是标识符或   PrimaryNoNewArray可能就足够了。甚至更严厉的限制   只允许标识符可以提供几乎所有附加信息   允许完整表达的实用性(强制声明   一个新的资源变量)在一个低得多的边际实施和   规范影响。“

     

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

答案 1 :(得分:8)

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

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

展望未来,try-with-resource可能会脱离时尚,取而代之的是lambda。例如

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

答案 2 :(得分:4)

尽管我不希望这样做,但其背后的基本原理是资源试用仅限于必须处理的项目的操作。它需要一个命名变量,因为它希望你在块内时对该变量做一些事情。我想这就像编译器说“如果你不打算实际使用资源,你为什么要尝试资源?”

现在你和我完全知道我们不想真正使用资源:相反,我们只是想确保它在我们完成它时已经关闭所以我们没有开发人员绕锁定系统。但是,像许多事情一样,他们不得不做出设计决策并且处于少数,我们没有得到这个功能。

答案 3 :(得分:1)

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

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

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

这里有两个缺点:

  1. finally块很烦人,每个关闭资源都必须为空安全
  2. 我们必须在块外声明资源才能在finally块中访问它们。因此,我们扩大了变量可访问的范围,这是不好的做法。
  3. Try-with-resource语法解决了这两个问题:

    1. finally根本不需要阻止。
    2. 资源变量只能在try块中访问,即应该知道的位置。
    3. 这就是可关闭资源必须是本地资源的原因。否则,try-with-resource语法的一个主要缺点是“禁用”。