Joe Bowbeer joe.bowbeer at
Fri Jun 28 14:05:59 PDT 2013

On Fri, Jun 28, 2013 at 1:20 PM, Brian Goetz <brian.goetz at> wrote:

> 1. What happens if close needs to throw an exception?  Why is this form
>> of close different from others?
> It was a mistake from Day 1 to allow Reader.close() and friends to throw
> anything checked.  I mean, what could a caller *possibly do* to respond to
> such an exception?  Close it again?  OK, live and learn.

Treat it like the IOException that it is!  How does an app respond to IO
exceptions?  They often give the user the chance to try again...  They
generally don't silently ignore or crash.

The proper handling of code like this involves a try-finally (resource
management) nested inside a try-catch (to manage IO exception), in which
case the IOException on close does not need special handling.

> When AutoCloseable came along, it would have been preferable for AC to
> support no exceptions on its close.  But since Closeable has to extend AC,
> and AC didn't want to be tied to IOException, its only option was to throw
> Exception.  Which no one wanted, but such is the price of compatibility
> with previous mistakes.
> New AC-style interfaces have the option to make this better by throwing
> nothing.  This was our first opportunity to do so.

I have a different interpretation of close throwing an exception.  In many
implementations of output streams and transactions everything happens in
the close() - in the flush technically - so unless you're arguing for
IOException unchecked, I think your reasoning has limited range.

Closing a Reader, as opposed to Writer, is more likely innocuous but the
programmer would still like to know about problems.  (I'm now wondering
about the File.walk API: does it throw IOException?  Otherwise, how does an
app know if the walk encountered an IO issue?)

I'm worried that if this API extends to output Streams, we are opening
ourselves up to silent errors.

Why is this API being treated as input only?  Is there some reason that it
will not be applied to writeable resources?

>  2. Why is this a close() method instead of a dispose() or release()
>> method?
> Because doing so would require a language change, and reopening a number
> of issues with try-with-resources.  If we want to build on TWR, our only
> choice right now is AutoCloseable.
>  Concerning names, I've lost track of what the expected programming style
>> for this is.  It would be a great aid if I could see three exemplary
>> snippets.
> Remember this is mostly for the StreamSupport crowd, who are building
> libraries to return streams.  Users will rarely call close() or onClose()
> or use MumbleCloseable.
> Here's two: concat and Files.lines.
>     public static IntStream concat(IntStream a, IntStream b) {
>         Objects.requireNonNull(a);
>         Objects.requireNonNull(b);
>         Spliterator.OfInt split = new Streams.ConcatSpliterator.**OfInt(
>                 a.spliterator(), b.spliterator());
>         IntStream stream = (a.isParallel() || b.isParallel())
>                            ? StreamSupport.**intParallelStream(split)
>                            : StreamSupport.intStream(split)**;
>         return stream.onClose(() -> { try { a.close(); }
>                                       finally { b.close(); }});
>     }
>     public static Stream<String> lines(Path path, Charset cs) throws
> IOException {
>         BufferedReader br = Files.newBufferedReader(path, cs);
>         return br.lines().onClose(Closeable.**asRunnable(br));
>     }


More information about the lambda-libs-spec-observers mailing list