9 ms·
Regarding the 'checked exception issue'; an alternative technique to the method-wrapping-lambda is to use a default interface method to implement the non-except
by steve_barham 12y ago
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.
- BrandonM 12y agoWe currently use the following pattern: interface ConsumerE<T, E extends Exception> { void accept(T t) throws E; } This actually works! The type inference is good enough to figure out the actual type of E. Note that Java 8 also includes specialized wrappers like RuntimeIOException. So it might be nice to extend your example: static <T, E extends Exception> Consumer<T> wrapped( Function<? super E, RuntimeException> wrapper, ConsumerE<T, E> consumer) { return (t) -> { try { consumer.accept(t); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw wrapper.apply((E) e); } }; } Used as follows: Consumer<String> printer = wrapped(RuntimeIOException::new, writer::write);
- phernandez 12y agoI was trying to work around this problem also and found this library: https://github.com/jOOQ/jOOL https://github.com/jOOQ/jOOL, from the guys at Jooq. They did all the hard work to wrap all the FunctionalInterfaces in unchecked exceptions. Hope this helps.
- BrandonM 12y agoThanks a lot for the pointer! That's most of what we need.