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:<p><pre><code> 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;
}
</code></pre>
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:<p><pre><code> try (Writer writer = new StringWriter()) {
final IOConsumer<String> ioPrinter = writer::write;
// hand ioPrinter off to something that expects a Consumer<String>
}
</code></pre>
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:<p><pre><code> static <T> Consumer<T> maybe(IOConsumer<T> consumer) {
return consumer;
}
try (Writer writer = new StringWriter()) {
final Consumer<String> printer = maybe(writer::write);
}
</code></pre>
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.