java 为什么 try-with-resource 需要一个局部变量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16588843/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does try-with-resource require a local variable?
提问by Miserable Variable
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 namedlocal variable at all.
参考我的问题java.util.concurrent.locks.Lock 的 AutoCloseable 包装器中的任何风险?,我想知道为什么 trhtry-with-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
}
回答by Zero3
The link in the comment by @McDowell reveals the correct answer in a blog post commentby Joe Darcy who led the Java Technology Specificationthat introduced the try-with-resources statement:
@McDowell 评论中的链接在Joe Darcy的博客文章评论中揭示了正确答案,他领导了引入 try-with-resources 语句的 Java 技术规范:
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
"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."
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,我们开始使用 try-with-resources 构造,它允许对资源使用通用表达式,包括方法调用。然而,专家组通过早期草案 ( http://jcp.org/aboutJava/communityprocess/edr/jsr334/index.html) 发现
“[对 try-with-resources 语句] 未来可能发生的变化是不再支持将资源指定为通用表达式。允许将通用表达式用作资源会导致非平凡的规范和实现复杂性。一个受限制的表达式可以是标识符或 PrimaryNoNewArray 可能就足够了。即使是仅允许标识符的更严格的限制也可以提供几乎所有的附加效用,即允许完整表达式(过度强制声明新资源变量)以低得多的边际实现和规范影响。”
到 JDK 7 结束时,我们想要的是资源的新变量声明或现有的最终/有效最终变量。我们只有时间在 7 中提供前者;在 9 中,我们也提供后者。
回答by ZhongYu
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.
至于为什么 Lock 不能自动关闭,我认为 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; } );
回答by corsiKa
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-with-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.
现在你我都清楚我们不想实际使用资源:相反,我们只是想确保它在我们完成后关闭,这样我们就没有开发人员来锁定系统。但就像很多事情一样,他们必须做出设计决定,而且作为少数,我们没有得到这个功能。
回答by AlexR
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:
这里有两个缺点:
finally
block is annoying and have to be null-safe for each closing resource- 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.
finally
块很烦人,对于每个关闭资源都必须是空安全的- 我们必须在块外声明资源才能在
finally
块中访问它们。因此,我们扩大了可访问变量的范围,这是不好的做法。
Try-with-resource syntax solves both problems:
Try-with-resource 语法解决了这两个问题:
finally
block is not needed at all.- The resource variable remains accessible into
try
block only, i.e. where it should be known.
finally
根本不需要块。- 资源变量仍然只能在
try
块中访问,即它应该被知道的地方。
This is why the closable resource must be local. Otherwise one of the main disadvantages of try-with-resource syntax is "disabled".
这就是为什么可关闭的资源必须是本地的。否则 try-with-resource 语法的主要缺点之一是“禁用”。