try-with-resources and null resource

Tim Peierls tim at peierls.net
Wed Jan 26 10:05:21 PST 2011


On Wed, Jan 26, 2011 at 8:58 AM, Rémi Forax <forax at univ-mlv.fr> wrote:

> This code doesn't throw NPE when initializing r with null:
>
>  R r = get();
> try {
>     maybeUse(r);
> } finally {
>     r.close();
>  }
>
>  Nor should this code:
>
>  try (
>     R r = get();
> ) {
>     maybeUse(r);
> }
>
>  --tim
>
>
> Again, you're talking about implementation of the construct and not
> semantics of the construct.
>

No, I am writing about what I think the semantics of the construct should
be. I'm drawing an analogy between two constructs, one old, one new, that
many users will see as similar, rightly or wrongly. Their expectations for
the new construct's semantics will be shaped by this perception. I claim
that most users won't expect NPE to be thrown immediately if the initializer
is null, and that they will expect NPE to be thrown on the first attempt to
dereference a null. They'll expect this because that's what happens in the
analogous case.

You can say the analogy is false, you can say that people should approach
this construct as being radically different from try-finally, you can even
say that most people are sloppy thinkers. But you can't change how they
think by wishing, and it would be wrong to design the feature without taking
such people into account.

(You could also claim that I'm wrong about how the average user will respond
to this new feature. But it doesn't sound like you're trying to make that
case.)



> Perhaps it's because try-with-resources reuses the same keyword as
> try/finally, which doesn't help.
>

To the contrary, I think this re-use of the try keyword will be very helpful
to users trying to understand the new construct.

I don't think most people will think about the new feature as being similar
to things like switch or enhanced for. Switch takes an expression, and
enhanced for uses a colon rather than equals, and thus doesn't look like a
regular declaration. (If anything, they'll see a connection between t-w-r
and the initialization clause of a traditional for loop.)


To make things crystal-clear, what should you [sic] be the semantics of:
> using(R r = get()) {
>   maybeUse(r);
> }
> if get() returns null?
>

I think you're asking whether the users' expectations would be different if
the construct used a different keyword. My answer: Maybe, but how is this
relevant? People won't be thinking about alternative design choices when
attempting to understand how the feature behaves.

It is crystal clear that if you were designing this language feature you'd
do it differently! :-)

--tim



More information about the coin-dev mailing list