Неправильный тип возврата в лямбда-выражении

Вопрос:Следующий код компилируется в IntelliJ и Eclipse, но компилятор JDK 1.8.0_25 жалуется. Во-первых, код. import java.util.function.Predicate; public abstract class MyStream { static MyStream create() { return null; } abstract MyStream filter(MyPredicate

Вопрос:

Следующий код компилируется в IntelliJ и Eclipse, но компилятор JDK 1.8.0_25 жалуется. Во-первых, код.

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); } }

Выход из javac 1.8.0_25:

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

Когда я заменяю ? super E просто E, JDK успешно компилируется.

Когда я заменяю filter(MyPredicate на filter(Predicate, JDK успешно компилируется.

Поскольку он работает с JDK 1.8.0_60, я подозреваю, что это ошибка компилятора.

Любые сведения о том, что вызвало это и когда оно было исправлено?

Лучший ответ:

Если выражение лямбда появляется в целевом типе с помощью подстановочных знаков (как в большинстве случаев)

Consumer<? super Boolean> consumer = b->{…}

возникает вопрос – какой тип лямбда-выражения; в частности, тип b.

Конечно, может быть много вариантов из-за подстановочных знаков; например мы могли бы явно выбрать

Consumer<? super Boolean> consumer = (Object b)->{…}

Однако, неявно, b следует вывести как Boolean. Это имеет смысл, так как потребителю следует подавать только Boolean.

http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.3

Если T – тип функционального интерфейса с параметром подстановочной подстановки и выражение лямбда неявно напечатано, то целевой целевой тип – это несимметричная параметризация T

(Вероятно, предполагается, что подстановочные знаки корректно используются для целевого типа, поэтому мы можем найти несколько веселых примеров, если предположение не выполняется)

Ответ №1

<? super E> включает Object, который не является Boolean. т.е.

MyPredicate<? super E>

Может быть

MyPredicate<Object>

и вы не можете вернуть Object как Boolean.

Попробуйте изменить lambda на:

MyStream.<Boolean> create().filter(b -> Boolean.TRUE.equals(b));

который будет компилироваться и выполняться без ошибки, не имеет значения типа потока, но вернет true для элементов, которые являются значениями true Boolean.

Оцените статью
Добавить комментарий