16

In the try-with-resources construct of Java 7, I can declare a resource in the try statement, and it will be closed automatically when it goes out of scope.

However, I don't find any indication of the scope of the resource made available. Specifically, is it available in the catch/finally blocks of the try block where it is declared?

I tried the following in Eclipse Kepler, but it's giving a mixed impression:

Resource variable is made available by Content Assist (Code Completion):

Content Assist suggests resource

Quick Fix suggests changing to resource variable, but this recursively produces the same problem it's trying to fix:

Redundant suggestion in Quick Fix

I would like to know what the correct scope limitation is, before raising a bug in the Eclipse Bug Tracker.

ADTC
  • 8,999
  • 5
  • 68
  • 93
  • Nambari, Sotirios, rocketboy, I can't accept one answer right now because all are good in their own terms. I will leave it for votes for a while before deciding on the best. Thanks for your efforts! – ADTC Sep 09 '13 at 04:31

4 Answers4

10

This syntax is called Extended try-with-resources

As per JLS:

try ResourceSpecification
    Block
Catchesopt
Finallyopt

Will be translated to:

try {
    try ResourceSpecification
        Block
}
Catchesopt
Finallyopt

So, in your example, your resource will be limited to inner try block, so not available for outer try/catch/finally.

EDIT:

my question does not have nested try blocks

By explicitly adding catch/finally block in your code, you are introducing nested try blocks.

kosa
  • 65,990
  • 13
  • 130
  • 167
  • 1
    Sorry, my question does not have nested `try` blocks. Can I know the relevance of your answer? – ADTC Sep 09 '13 at 04:18
  • 1
    @ADTC: Please refer language specification link in answer. Refer section 14.20.3.2. – kosa Sep 09 '13 at 04:21
8

Update from 2017 after Java 9 release

Now with Java 9 we have more syntactic sugar and we can have a resource declared outside the try-catch block but still handled properly. That's why with Java 9 the Try-With-Resources has been improved introducing a new syntax:

InputStream stream = new MyInputStream(...)
try (stream) {
   // do something with stream being sure that is going to be closed at the end
} catch(IOException e) {
   // the resource (in this case, the stream) has been closed - see the end
}

Note that this syntax will result in a compile time error for Java version 8 or minor

This is more "natural" way of writing even though in most use cases we don't need the resource outside the scope of the try block. The only restriction is that the reader variable should be effectively final or just final.

From the docs, using try with resources, it mentions 'in a try-with-resources statement, any catch or finally block is run after the resources declared have been closed'.

Matthew
  • 3
  • 2
rakwaht
  • 3,666
  • 3
  • 28
  • 45
5

In addition to @Nambari's answer:

A try-with-resources statement can have catch and finally blocks just like an ordinary try statement. In a try-with-resources statement, any catch or finally block is run after the resources declared have been closed.

That pretty much explains the behaviour, your resource goes out of scope in your explicit catch/finally block.

Reference

rocketboy
  • 9,573
  • 2
  • 34
  • 36
4

The correct scope limitation is within the declaration part (...) and the actual try block.

The JLS states

The scope of a variable declared in the ResourceSpecification of a try-with-resources statement (§14.20.3) is from the declaration rightward over the remainder of the ResourceSpecification and the entire try block associated with the try-with-resources statement.

So from the point it is declared in the ResourceSpecification (...) of the try onwards until the final closing } bracket of the try Block.

TryWithResourcesStatement:
    try ResourceSpecification Block Catchesopt Finallyopt

ResourceSpecification:
    ( Resources ;opt )

Resources:
    Resource
    Resource ; Resources

Resource:
    VariableModifiersopt Type VariableDeclaratorId = Expression
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Do you mean **the resource variable** is not supposed to be available in catch/finally blocks? Please elaborate your answer. It is currently as vague as the Java 7 documentation.. – ADTC Sep 09 '13 at 04:12
  • @ADTC Only available in the `try` block means only until `try (..) {}` ends. Not in `catch`, not in `finally` – Sotirios Delimanolis Sep 09 '13 at 04:14
  • @ADTC The JLS has a drawing for us, see my edit. It is contained within `ResourceSpecification` and `Block`. the Java 7 documentation is pretty explicit. – Sotirios Delimanolis Sep 09 '13 at 04:17
  • Thank you. I guess this means I can file a bug with Eclipse that the _Code Completion_ **must not** make the resource available in `catch`/`finally` blocks. Right? – ADTC Sep 09 '13 at 04:19
  • @ADTC Sure, it looks like it. – Sotirios Delimanolis Sep 09 '13 at 04:21