Reputation: 674
I am trying to wrap methods which throws checked exceptions.. I am following steps told in this url: https://www.rainerhahnekamp.com/en/ignoring-exceptions-in-java/
Interestingly when I write the code like this:
IntStream.range(1, locales.length)
.mapToObj(i -> locales[i].toString())
.forEach(wrap(this::testLocale));
it is working fine but when I write like this:
IntStream.range(1, locales.length)
.mapToObj(i -> locales[i].toString())
.forEach(s -> wrap(testLocale(s)));
Intellij is complaining "Unhandled Exception: java.lang.Exception"
here testLocale looks like this:
void testLocale(String s) throws Exception
The wrap function looks like this:
public static <T> Consumer<T> wrap(WrapConsumer<T> wrapper) {
return t -> {
try {
wrapper.accept(t);
} catch(Exception exception) {
throw new RuntimeException(exception);
}
};
}
and WrapConsumer is a function interface with Consumer signature:
@FunctionalInterface
public interface WrapConsumer<T> {
void accept(T t) throws Exception;
}
I am banging my head trying to understand why Intellij is complaining based on how I write the lambda
Upvotes: 3
Views: 172
Reputation: 120848
You are supposed to provide a wrapped consumer to forEach
via:
.forEach(wrap(this::testLocale));
what you are doing via s -> wrap(testLocale(s))
is provide a new consumer that still can't handle the checked Exception.
Probably simpler to understand would be that forEach
accepts a Consumer
that has a method definition of:
void accept(T t); // does not define to throw the checked Exception
When you do forEach(s -> ...)
, it is this Consumer::accept
that you are using.
On the other hand that forEach(wrap(this::testLocale));
will return a Consumer
still, but by accepting as input a WrapConsumer<T> wrapper
that does declare to throw that Exception
via:
void accept(T t) throws Exception;
Upvotes: 3
Reputation: 2210
Just complementing what Eugene answered, you are expecting with the method wrap() a consumer as param, not a invocation method returning void.
You can prove this by removing the throws Exception from the testLocale method.
The IDE will them give you the error:
"reason: no instance(s) of type variable(s) T exist so that void conforms to WrapConsumer<T>"
The similar code for the one you wrote (right consumer):
IntStream.range(1, locales.length)
.mapToObj(i -> locales[i].toString())
.forEach(wrap(this::testLocale));
Would be:
IntStream.range(1, locales.length)
.mapToObj(i -> locales[i].toString())
.forEach(wrap(l-> testLocale(l)));
Upvotes: 2
Reputation: 45309
You're just missing the correct lambda syntax. Your current code is calling wrap
with a void
argument: wrap(testLocale(s))
- (testLocale(s)
has a void return type)
The correct lambda expression that you need is:
.forEach(wrap(s -> testLocale(s)));
wrap
returns a function, so you don't need delayed execution for it (i.e., no need for a function that calls wrap
).
Upvotes: 2