为什么试用资源需要一个局部变量?

时间:2021-07-30 16:48:53

With reference to my question Any risk in a AutoCloseable wrapper for java.util.concurrent.locks.Lock?, I am wondering why trh try-with-resource require a named local variable at all.

关于我的问题,在java.util.concurrent.locks.Lock的自动关闭包装器中有任何风险吗?,我想知道为什么trh try- resource需要一个命名的局部变量。

My current usage is as follows:

我目前的使用情况如下:

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

The variable l is unused inside the try block and only pollutes the namespace. From what I can remember the analogous C# using statement does not require a local named variable.

变量l在try块中未使用,只会污染名称空间。我记得类似的c# using语句并不需要一个本地命名变量。

Is there any reason the following could not have been supported, with an anonymous local variable that is closed at the end of try block?

是否有任何理由不支持以下内容,使用一个在try块末尾关闭的匿名局部变量?

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

4 个解决方案

#1


11  

The link in the comment by @McDowell reveals the correct answer in a blog post comment by Joe Darcy who led the Java Technology Specification that introduced the try-with-resources statement:

@McDowell评论中的链接揭示了乔·达西的博客评论的正确答案。乔·达西领导了Java技术规范,引入了try-with-resources语句:

Back in JDK 7, we started with a try-with-resources construct like that allowed a general expression to be used for the resource, including a method call. However, the expert group found by the early draft review (http://jcp.org/aboutJava/communityprocess/edr/jsr334/index.html) that

在JDK 7中,我们从一个带有资源的try构造开始,这种构造允许对资源使用通用表达式,包括方法调用。然而,专家组在早期的草案评审(http://jcp.org/aboutJava/communityprocess/edr/jsr334/index.html)中发现了这一点

"A possible future change [to the try-with-resources statemenbt] is dropping support for a resource to be specified as a general Expression. Nontrivial specification and implementation complexities arise from allowing a general Expression to be used as resource. A restricted expression that could be an identifier or a PrimaryNoNewArray may suffice. Even the more severe restriction of just allowing an identifier may provide nearly all the additional utility of allowing a full expression (over forcing the declaration of a new resource variable) at a much lower marginal implementation and specification impact."

“(对带有资源的try- resources statemenbt的)一个可能的未来更改是取消对要指定为通用表达式的资源的支持。”不平凡的规范和实现的复杂性来自于允许将一个通用表达式用作资源。可以是标识符或PrimaryNoNewArray的受限表达式可能就足够了。即使是允许标识符的更严格的限制也可能提供几乎所有的附加效用,即允许在更低的边际实现和规范影响下使用完整的表达式(而不是强制声明新的资源变量)。

By the end of JDK 7, what we wanted was a fresh variable declaration for the resource or an existing final / effectively final variable. We only had time to provide the former in 7; in 9, we are providing the latter too.

到JDK 7的末尾,我们想要的是资源的一个新的变量声明,或者一个现有的最终/有效的最终变量。我们只有7分钟的时间提供前者;在9,我们也提供了后者。

#2


8  

Among the use cases that they were considering, most would need to access the resource inside the block, for example, open file - read/write file - close file. They would not have made this design decision if they thought there are a lot of use cases where the local variable is unused.

在他们考虑的用例中,大多数都需要访问块中的资源,例如,打开文件—读/写文件—关闭文件。如果他们认为有大量的用例本地变量未使用,他们就不会做出这个设计决策。

As to why Lock isn't auto-closeable, I think Doug Lea isn't too concerned with syntax matter, he focuses on solving the hard problem. Others can always add syntax sugar on top of his utilities.

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

Looking forward, try-with-resource probably will fall out of fashion, replaced by lambda. For example

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

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

#3


4  

As much as I wish it wasn't, the rationale behind it is that the try-with-resources is intended strictly for operations on the item that must be disposed of. It requires a named variable because it expects that you will do something with that variable while you're inside the block. I guess it's like the compiler saying "If you don't plan on actually using the resource, why are you doing a try-with-resources?"

尽管我希望它不是,但它背后的基本原理是,带有资源的try严格用于必须处理的项目的操作。它需要一个命名变量,因为它期望您在块内部时对该变量做一些事情。我猜这就像编译器说“如果你不打算实际使用资源,为什么要使用资源进行try- resources?”

Now you and I know full well that we don't want to actually use the resource: rather, we just want to make sure it's closed when we're done with it so we don't have devs going around locking up the system. But like so many things, they had to make design decisions and being in the minority, we didn't get the feature.

现在你和我都很清楚,我们并不想实际使用这个资源:相反,我们只是想确保当我们用完它时它是关闭的,这样我们就不会让devs到处锁定系统。但就像很多事情一样,他们必须做出设计决定,而且他们是少数,我们没有得到这个特性。

#4


1  

I think that inability to use local variable was the trigger for try-with-resource.

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

Prior to java 1.7 you had to write something like this:

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

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

There are 2 disadvantages here:

这里有两个缺点:

  1. finally block is annoying and have to be null-safe for each closing resource
  2. finally块是烦人的,必须为每个关闭资源都是空的。
  3. We must declare resources outside the block just be able to access them in finally block. Therefore we enlarge the scope where the variables are accessible that is bad practice.
  4. 我们必须声明块之外的资源,以便能够在finally块中访问它们。因此,我们扩大了变量可访问的范围,这是不好的做法。

Try-with-resource syntax solves both problems:

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

  1. finally block is not needed at all.
  2. 最后,完全不需要block。
  3. The resource variable remains accessible into try block only, i.e. where it should be known.
  4. 资源变量仅在try块中是可访问的,即应该知道它在哪里。

This is why the closable resource must be local. Otherwise one of the main disadvantages of try-with-resource syntax is "disabled".

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

#1


11  

The link in the comment by @McDowell reveals the correct answer in a blog post comment by Joe Darcy who led the Java Technology Specification that introduced the try-with-resources statement:

@McDowell评论中的链接揭示了乔·达西的博客评论的正确答案。乔·达西领导了Java技术规范,引入了try-with-resources语句:

Back in JDK 7, we started with a try-with-resources construct like that allowed a general expression to be used for the resource, including a method call. However, the expert group found by the early draft review (http://jcp.org/aboutJava/communityprocess/edr/jsr334/index.html) that

在JDK 7中,我们从一个带有资源的try构造开始,这种构造允许对资源使用通用表达式,包括方法调用。然而,专家组在早期的草案评审(http://jcp.org/aboutJava/communityprocess/edr/jsr334/index.html)中发现了这一点

"A possible future change [to the try-with-resources statemenbt] is dropping support for a resource to be specified as a general Expression. Nontrivial specification and implementation complexities arise from allowing a general Expression to be used as resource. A restricted expression that could be an identifier or a PrimaryNoNewArray may suffice. Even the more severe restriction of just allowing an identifier may provide nearly all the additional utility of allowing a full expression (over forcing the declaration of a new resource variable) at a much lower marginal implementation and specification impact."

“(对带有资源的try- resources statemenbt的)一个可能的未来更改是取消对要指定为通用表达式的资源的支持。”不平凡的规范和实现的复杂性来自于允许将一个通用表达式用作资源。可以是标识符或PrimaryNoNewArray的受限表达式可能就足够了。即使是允许标识符的更严格的限制也可能提供几乎所有的附加效用,即允许在更低的边际实现和规范影响下使用完整的表达式(而不是强制声明新的资源变量)。

By the end of JDK 7, what we wanted was a fresh variable declaration for the resource or an existing final / effectively final variable. We only had time to provide the former in 7; in 9, we are providing the latter too.

到JDK 7的末尾,我们想要的是资源的一个新的变量声明,或者一个现有的最终/有效的最终变量。我们只有7分钟的时间提供前者;在9,我们也提供了后者。

#2


8  

Among the use cases that they were considering, most would need to access the resource inside the block, for example, open file - read/write file - close file. They would not have made this design decision if they thought there are a lot of use cases where the local variable is unused.

在他们考虑的用例中,大多数都需要访问块中的资源,例如,打开文件—读/写文件—关闭文件。如果他们认为有大量的用例本地变量未使用,他们就不会做出这个设计决策。

As to why Lock isn't auto-closeable, I think Doug Lea isn't too concerned with syntax matter, he focuses on solving the hard problem. Others can always add syntax sugar on top of his utilities.

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

Looking forward, try-with-resource probably will fall out of fashion, replaced by lambda. For example

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

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

#3


4  

As much as I wish it wasn't, the rationale behind it is that the try-with-resources is intended strictly for operations on the item that must be disposed of. It requires a named variable because it expects that you will do something with that variable while you're inside the block. I guess it's like the compiler saying "If you don't plan on actually using the resource, why are you doing a try-with-resources?"

尽管我希望它不是,但它背后的基本原理是,带有资源的try严格用于必须处理的项目的操作。它需要一个命名变量,因为它期望您在块内部时对该变量做一些事情。我猜这就像编译器说“如果你不打算实际使用资源,为什么要使用资源进行try- resources?”

Now you and I know full well that we don't want to actually use the resource: rather, we just want to make sure it's closed when we're done with it so we don't have devs going around locking up the system. But like so many things, they had to make design decisions and being in the minority, we didn't get the feature.

现在你和我都很清楚,我们并不想实际使用这个资源:相反,我们只是想确保当我们用完它时它是关闭的,这样我们就不会让devs到处锁定系统。但就像很多事情一样,他们必须做出设计决定,而且他们是少数,我们没有得到这个特性。

#4


1  

I think that inability to use local variable was the trigger for try-with-resource.

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

Prior to java 1.7 you had to write something like this:

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

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

There are 2 disadvantages here:

这里有两个缺点:

  1. finally block is annoying and have to be null-safe for each closing resource
  2. finally块是烦人的,必须为每个关闭资源都是空的。
  3. We must declare resources outside the block just be able to access them in finally block. Therefore we enlarge the scope where the variables are accessible that is bad practice.
  4. 我们必须声明块之外的资源,以便能够在finally块中访问它们。因此,我们扩大了变量可访问的范围,这是不好的做法。

Try-with-resource syntax solves both problems:

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

  1. finally block is not needed at all.
  2. 最后,完全不需要block。
  3. The resource variable remains accessible into try block only, i.e. where it should be known.
  4. 资源变量仅在try块中是可访问的,即应该知道它在哪里。

This is why the closable resource must be local. Otherwise one of the main disadvantages of try-with-resource syntax is "disabled".

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