简体   繁体   English

为什么 try-with-resources 不适用于字段变量?

[英]Why doesn't try-with-resources work with field variables?

This is my very first question on SO and I'm confused there isn't a similar question yet!这是我关于 SO 的第一个问题,我很困惑还没有类似的问题!

So the question is:所以问题是:

Why doesn't try-with-resources work with field variables?为什么 try-with-resources 不适用于字段变量?

Or in other words: Why do I always need a local variable for that?或者换句话说:为什么我总是需要一个局部变量?

Here goes some example code:下面是一些示例代码:

public class FileWriteTest {

    public FileWriter file;

    public void workingDemo() {

        try(FileWriter file = new FileWriter(new File("someFilePath")) {
            // do something
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void notWorkingDemo() {

        file = null;

        try(file = new FileWriter(new File("someFilePath")) {
            // do something
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

May anyone explain me why there is this convention?谁能解释一下为什么有这个约定?

An instance variable may be changed at any point during the execution of the try-with-resources block.实例变量可以在 try-with-resources 块执行期间的任何时候更改。 This would break its invariant and prevent the cleanup.这将打破其不变性并阻止清理。 Note that the local variable is implictly final, for the same reason.请注意,出于同样的原因,局部变量是隐式最终变量。

BTW a better question is, why does Java force us to declare a local variable, even if we don't refer to it within the block.顺便说一句,一个更好的问题是,为什么 Java强制我们声明一个局部变量,即使我们不在块中引用它。 C#, for example, doesn't require this.例如,C# 不需要这个。

Update: with version 9, Java has stopped forcing us:更新:在第 9 版中,Java 不再强迫我们:

private final Some obj = new Some();

try (obj) { 
  // obj captured in a hidden local variable, resource closed in the end
}

I suspect the designers considered using a field a bad idea as this allow the object to escape the region of usage.我怀疑设计者认为使用一个字段是一个坏主意,因为这允许对象逃离使用区域。 ie it is only valid in the try block so you shouldn't be able to access it anywhere else.即它仅在 try 块中有效,因此您不应在其他任何地方访问它。

Section 14.20.3 of the Java Language Specification states it will only work with local variables. Java 语言规范的第 14.20.3 节声明它仅适用于局部变量。

Why is this?为什么是这样? My guess is checking for definite assignment and escapage (the local variable doesn't escape into the scope of another method).我的猜测是检查确定的赋值和转义(局部变量不会转义到另一个方法的范围内)。 A field may be initialized anywhere in the class.字段可以在类中的任何地方初始化。 My guess is that by validating it's a local variable, it's much simpler to analyse.我的猜测是,通过验证它是一个局部变量,分析起来要简单得多。

With Java 9, They added support for try with resources with variables.在 Java 9 中,他们添加了对带有变量的资源的尝试支持。

    // Original try-with-resources statement from JDK 7 or 8
    try (Resource r1 = resource1;
         Resource r2 = resource2) {
        // Use of resource1 and resource 2 through r1 and r2.
    }

    // New and improved try-with-resources statement in JDK 9
    try (resource1;
         resource2) {
        // Use of resource1 and resource 2.
    }

https://blogs.oracle.com/darcy/more-concise-try-with-resources-statements-in-jdk-9 https://blogs.oracle.com/darcy/more-concise-try-with-resources-statements-in-jdk-9

First off, I think it would be bad practice to have a variable/resource which is used at multiple places.首先,我认为在多个地方使用变量/资源是不好的做法。 If it is not opened in the try , then you cannot close it afterwards, if it is opened there, then you won't need a non-local variable.如果它没有在try打开,那么你之后就不能关闭它,如果它在那里打开,那么你就不需要非局部变量。 This leads to "second": If you have a resource open already, then you need to close it somewhere else explicitly, otherwise the autoclose wouldn't know if it is open or not.这导致“第二个”:如果您已经打开了一个资源,那么您需要在其他地方明确关闭它,否则自动关闭将不知道它是否打开。

So, IMHO it makes only sense to handle it the way it is specified in the specification.因此,恕我直言,按照规范中指定的方式处理它才有意义。

It may have to do with consistency with the language specifications.这可能与语言规范的一致性有关。 Whenever a variable is declared between two brackets, it is encapsulated inside and cannot be accessed from the outside:每当一个变量在两个括号之间声明时,它就被封装在里面,不能从外面访问:

anything
{
int var;
}

// cannot access var from here!

Why shoul try { } be an exception ?为什么要 try { } 是一个例外?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM