为什么不尝试使用资源来处理字段变量?

时间:2013-06-21 12:31:48

标签: java java-7 try-with-resources

这是我关于SO的第一个问题,我很困惑,还没有类似的问题!

所以问题是:

  

为什么try-with-resources不能使用字段变量?

或换句话说:为什么我总是需要一个局部变量?

这里有一些示例代码:

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();
        }

    }

}

任何人都可以解释为什么有这个惯例?

6 个答案:

答案 0 :(得分:15)

在try-with-resources块执行期间,可以随时更改实例变量。这将破坏其不变性并防止清理。请注意,由于同样的原因,局部变量显然是最终的。

BTW一个更好的问题是,为什么Java 强制我们声明一个局部变量,即使我们在块中没有引用它。例如,C#不需要这个。

答案 1 :(得分:7)

我怀疑设计师认为使用字段是一个坏主意,因为这允许对象逃离使用区域。即它仅在try块中有效,因此您无法在其他任何地方访问它。

答案 2 :(得分:4)

Section 14.20.3Java Language Specification个{{3}}只能使用局部变量。

这是为什么?我的猜测是检查明确的赋值和转义(局部变量不会转移到另一个方法的范围内)。可以在类中的任何位置初始化字段。我的猜测是,通过验证它是一个局部变量,分析起来要简单得多。

答案 3 :(得分:1)

首先,我认为拥有一个在多个地方使用的变量/资源是不好的做法。如果未在try中打开,则之后无法关闭它,如果在那里打开,则不需要非局部变量。 这导致“第二”:如果您已经打开了资源,那么您需要在其他地方明确地关闭它,否则autoclose将不知道它是否打开。

所以,恕我直言,只有在规范中指定的方式处理它才有意义。

答案 4 :(得分:1)

使用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

答案 5 :(得分:0)

这可能与语言规范的一致性有关。 每当在两个括号之间声明变量时,它就封装在内部,不能从外部访问:

anything
{
int var;
}

// cannot access var from here!

为什么要尝试{}成为例外?