1

I noticed that this won't compile:

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

Only a new variable works at this point:

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

My intuition is that only a new object should be required, but apparently a new reference is needed. Clearly this is a result of compile-time type checking, but why doesn't the old reference work?

2 Answers 2

2

The answer is simple, because it will be closed after the try with resources completes. More specifically,

JLS 14.20.3. try-with-resources says in part (bold added),

A ResourceSpecification declares one or more local variables with initializer expressions to act as resources for the try statement.

A resource declared in a ResourceSpecification is implicitly declared final (§4.12.4) if it is not explicitly declared final.

The type of a variable declared in a ResourceSpecification must be a subtype of AutoCloseable, or a compile-time error occurs.

Sign up to request clarification or add additional context in comments.

1 Comment

What is the link between the object being closed and it being a local variable? References in the outer scope could be closed, then re-initialized.
1

For a most unsatisfactory answer, because the grammar defined in the specification requires a variable declaration. Looking at the Specification 14.20.3 the grammar is

TryWithResourcesStatement: try ResourceSpecification Block Catchesopt Finallyopt ResourceSpecification: ( Resources ;opt ) Resources: Resource Resource ; Resources Resource: VariableModifiers[opt] Type VariableDeclaratorId = Expression 

We can see the TryWithResourcesStatement requires a ResourceSpecification which is one or more Resource surrounded by round brackets and separated with semi-colons. Each resource requires a type and a name (Type and VariableDeclaratorId).

Therefor the compiler requires it because the specification requires it. You would need to delve into the process of the creation of this feature to find out why it was deemed necessary.

2 Comments

From the standpoint of the spec, I think @Elliot has the keyword in bold in his answer. If the variable has to be local, then that explains why the the type identifier is needed.
I would suggest the important word in @Elliots answer was declares in "A ResourceSpecification declares one or more...". The variable in the OP was a local variable (scoped in the same block as the try-with-resource block. But to say the ResourceSpecification declares a variable has a very specific meaning. Again it come down to "because the spec says so" Elliot prefers the text description, I prefer the formal grammar, both say the same.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.