Comment

Comment by steve_barham

Regarding the 'checked exception issue'; an alternative technique to the method-wrapping-lambda is to use a default interface method to implement the non-exceptional interface, which delegates to the possibly-exceptional method. It's a bit fussy, but it's a nice technique to know:

    interface IOConsumer<T> extends Consumer<T> {
        @Override
        default void accept(T t) {
            try { 
                maybeAccept(t); 
            } catch (IOException ie) { 
                throw new RuntimeException(ie); }
            }

        void maybeAccept(T t) throws IOException;
    }
As IOConsumer<T> is also a Consumer<T>, if you can assign the lambda to an IOConsumer<T> it will get this wrapping behaviour automatically. So your code might look something like:

        try (Writer writer = new StringWriter()) {
            final IOConsumer<String> ioPrinter = writer::write;

            // hand ioPrinter off to something that expects a Consumer<String>
        }
This is by no means beautiful; for 'writer::write' to be treated as an IOConsumer<T> requires that the target type be IOConsumer<T>, so typically would require an interim assignment. It does allow us to simplify the 'wrapping' method, though, so that lambdas can again be used as one-liners:

    static <T> Consumer<T> maybe(IOConsumer<T> consumer) {
        return consumer;
    }

    try (Writer writer = new StringWriter()) {
        final Consumer<String> printer = maybe(writer::write);
    }
It would be nice not to have these wrinkles, but I think Java 8 has done a fairly decent job of preserving backwards compatibility while introducing language features and APIs which feel like a vast improvement. I'd love to see reified generics in the future, particularly if the type parameter can be extended to support primitives.
parent steve_barham 12 years ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton