我注意到这不会编译:
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")) {
}
我的直觉是,只需要一个新对象,但显然需要一个新的参考。显然,这是编译时类型检查的结果,但为什么没有旧的参考工作呢?
答案 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
被圆括号包围并用分号分隔。每个资源都需要一个类型和名称(Type
和VariableDeclaratorId
)。
因此,编译器需要它,因为规范需要它。您需要深入研究创建此功能的过程,以找出其被认为必要的原因。