这是我关于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();
}
}
}
任何人都可以解释为什么有这个惯例?
答案 0 :(得分:15)
在try-with-resources块执行期间,可以随时更改实例变量。这将破坏其不变性并防止清理。请注意,由于同样的原因,局部变量显然是最终的。
BTW一个更好的问题是,为什么Java 强制我们声明一个局部变量,即使我们在块中没有引用它。例如,C#不需要这个。答案 1 :(得分:7)
我怀疑设计师认为使用字段是一个坏主意,因为这允许对象逃离使用区域。即它仅在try块中有效,因此您无法在其他任何地方访问它。
答案 2 :(得分:4)
这是为什么?我的猜测是检查明确的赋值和转义(局部变量不会转移到另一个方法的范围内)。可以在类中的任何位置初始化字段。我的猜测是,通过验证它是一个局部变量,分析起来要简单得多。
答案 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!
为什么要尝试{}成为例外?