bad return type in lambda expression
Solution 1
If a lambda expression appears in a target type with wildcards (as in most cases)
Consumer<? super Boolean> consumer = b->{...}
the question arises - what's the type of the lambda expression; in particular, the type of b
.
Of course, there could be many choices due to the wildcards; e.g. we could explicitly choose
Consumer<? super Boolean> consumer = (Object b)->{...}
However, implicitly, b
should be inferred as Boolean
. This makes sense since the consumer should only be fed with Boolean
anyway.
http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.3
If T is a wildcard-parameterized functional interface type and the lambda expression is implicitly typed, then the ground target type is the non-wildcard parameterization of T
(This probably assumes that wildcards are use properly variance-wise on the target type; we might find some hilarious examples if the assumption doesn't hold)
Solution 2
<? super E>
includes Object
, which isn't a Boolean
. ie
MyPredicate<? super E>
Could be a
MyPredicate<Object>
and you can't return an Object
as a boolean
.
Try changing your lambda to:
MyStream.<Boolean> create().filter(b -> Boolean.TRUE.equals(b));
which will compile and execute without error not matter the type of the stream, but will return true
for elements that are true
Boolean
values.
Related videos on Youtube
Roland Illig
Updated on October 13, 2020Comments
-
Roland Illig over 3 years
The following code compiles fine in IntelliJ and Eclipse, but the JDK compiler 1.8.0_25 complains. First, the code.
import java.util.function.Predicate; public abstract class MyStream<E> { static <T> MyStream<T> create() { return null; } abstract MyStream<E> filter(MyPredicate<? super E> predicate); public interface MyPredicate<T> extends Predicate<T> { @Override boolean test(T t); } public void demo() { MyStream.<Boolean> create().filter(b -> b); MyStream.<String> create().filter(s -> s != null); } }
The output from javac 1.8.0_25 is:
MyStream.java:18: error: incompatible types: incompatible parameter types in lambda expression MyStream.<Boolean> create().filter(b -> b); ^ MyStream.java:18: error: incompatible types: bad return type in lambda expression MyStream.<Boolean> create().filter(b -> b); ^ ? super Boolean cannot be converted to boolean MyStream.java:19: error: bad operand types for binary operator '!=' MyStream.<String> create().filter(s -> s != null); ^ first type: ? super String second type: <null> MyStream.java:19: error: incompatible types: incompatible parameter types in lambda expression MyStream.<String> create().filter(s -> s != null); ^ Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output 4 errors
When I replace
? super E
with simplyE
, JDK compiles successfully.When I replace
filter(MyPredicate
withfilter(Predicate
, JDK compiles successfully.Since it works with JDK 1.8.0_60, I suspect it is a compiler bug.
Any details on what caused this and when it has been fixed?
-
ZhongYu over 8 yearsyes, I too believe it is a compiler bug. try workaround
filter((Boolean b)->b))
-
-
ZhongYu over 8 yearsno - while the target type is
Predicate<? super Boolean>
, the type of the lambda expression should bePredicate<Boolean>
. (jls#12.27.3). Thereforeb
has a static type ofBoolean