Please: try-with-resouces Lock support!

Reinier Zwitserloot reinier at zwitserloot.com
Wed Mar 9 07:15:41 PST 2011


This snippet:

try (Resource r = getResource()) {
   .....
} catch (SomeException e) {
   ... do something with r....
}


implies that getResource() is not expected to fail. This is quite different
from for example an inputstream:

try (InputStream r = new FileInputStream(file)) { ... }

where an exception on the constructor call is expected and the current
specified behaviour of ARM matches this expectation (notably: that it
includes the initializing expression as part of the 'try').

There are a few solutions when the expectation is for the expression not to
fail as in the getResource example:

(1) Do *NOT* consider the expression as part of the 'try'. Short of
introducing some new keyword to specify which behaviour you want, Stephen's
example of try (Resource r = ...) { try { ..... }} does exactly that, and is
the only way to do this.

(2) Allow both with the same try statement. However, as in practice any
expression can theoretically fail with any exception, the solution would
have to be that 'r' is set to null if the initializing expression does not
complete normally. The syntax sugar to make this work isn't trivial but it
can be done.

One could then write:

try (Resource r = getResource()) {
   ....
} catch (Exception e) {
    icon = Icons.DEFAULT_ICON;
    logger.log("App icon resource " + r.getURL() + " is not available", e);
}

and if the exception that triggered the catch block to run occurred in the
evaluation of "getResource()", the above code would produce an NPE on the
log line. Better than a core dump, I guess. As with any null resource, such
a resource will not be closed, and no exception is caused by the fact that
'r' is null when its time to clean it up. (which would be following the
execution of the catch block).

Whether doing this is a good idea is something I leave to the readers, but
it is another consistent alternative and does look slightly cleaner, though
there's far more magic going on with this version.


 --Reinier Zwitserloot



On Sat, Mar 5, 2011 at 9:18 PM, Neal Gafter <neal at gafter.com> wrote:

> In the try-with-resource language construct, exceptions thrown during the
> construction of the resource are caught in the catch clauses.  Therefore,
> making the resource in scope be within the catch clause would be providing
> access to a variable that is not definitely assigned.  Since a variable
> that
> is final (by the try-with-resources specification), not definitely assigned
> (because the exception might have occurred during the resource expression),
> and not definitely unassigned (because the exception might have occurred
> during the try block), it cannot be used in any way.  There is therefore no
> point in making the variable be in scope within the catch clause.
>
> The correct thing to do is Stephen' suggestion:
>
> On Sat, Mar 5, 2011 at 11:08 AM, Stephen Colebourne <scolebourne at joda.org
> >wrote:
>
> > But there is a "hack" solution:
> >
> > try(Resource r  = getResource()) {try {
> >     doSomething(r);
> > } catch (ResourceException e) {
> >    System.out.println(e + " from " + r); // r undefined here
> > }}
> >
> > Not ideal.
> >
>
> This is the correct solution, and it is both ideal and not a hack.  I'm not
> sure I agree with your spacing and placement of curly braces, but that is a
> style issue.  The semantics of this code are different (than a catch on the
> try-with-resources statement) because the catch clause here only catches
> exceptions thrown from within the inner try block.  If you want to use the
> resource variable, that is exactly what you need.
>
> At worst, this exchange demonstrates that the try-with-resources
> specification is piling too much complexity on the already overly complex
> try statement.
>
> Cheers,
> Neal
>
>



More information about the coin-dev mailing list