为什么我不能在try-with-resources try子句中重用引用变量?

时间:2014-10-13 01:19:51

标签: java java-7

我注意到这不会编译:

PrintWriter printWriter = new PrintWriter("test.txt");
printWriter.append('a');
printWriter.close();
printWriter = null;

try(printWriter = new PrintWriter("test.txt")) {

}

with:Error:(17, 24) java: <identifier> expected

此时只有一个新变量有效:

try(PrintWriter printWriter2 = new PrintWriter("test.txt")) {

}

我的直觉是,只需要一个新对象,但显然需要一个新的参考。显然,这是编译时类型检查的结果,但为什么没有旧的参考工作呢?

2 个答案:

答案 0 :(得分:2)

答案很简单,因为在资源完成尝试后它将被关闭。更具体地说,

JLS 14.20.3. try-with-resources部分说明(粗体添加),

  

ResourceSpecification使用初始化表达式声明一个或多个局部变量,以充当try语句的资源。

     

如果未明确声明为final,则在ResourceSpecification中声明的资源将被隐式声明为final(§4.12.4)。

     

在ResourceSpecification中声明的变量类型必须是AutoCloseable的子类型,否则会发生编译时错误。

答案 1 :(得分:1)

对于最不满意的答案,因为规范中定义的语法需要变量声明。查看Specification 14.20.3语法是

TryWithResourcesStatement:
    try ResourceSpecification Block Catchesopt Finallyopt

ResourceSpecification:
    ( Resources ;opt )

Resources:
    Resource
    Resource ; Resources

Resource:
    VariableModifiers[opt] Type VariableDeclaratorId = Expression

我们可以看到TryWithResourcesStatement需要ResourceSpecification,其中一个或多个Resource被圆括号包围并用分号分隔。每个资源都需要一个类型和名称(TypeVariableDeclaratorId)。

因此,编译器需要它,因为规范需要它。您需要深入研究创建此功能的过程,以找出其被认为必要的原因。