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 simply E
, JDK compiles successfully.
When I replace filter(MyPredicate
with filter(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?
<? super E>
includesObject
, which isn't aBoolean
. ieCould be a
and you can't return an
Object
as aboolean
.Try changing your lambda to:
which will compile and execute without error not matter the type of the stream, but will return
true
for elements that aretrue
Boolean
values.If a lambda expression appears in a target type with wildcards (as in most cases)
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
However, implicitly,
b
should be inferred asBoolean
. This makes sense since the consumer should only be fed withBoolean
anyway.http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.3
(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)