我正在尝试将Consumer
转换为Runnable
。以下代码在Eclipse IDE中不生成任何编译器错误。
Consumer<Object> consumer;
Runnable runnable;
Object value;
...
runnable = () -> consumer.accept(value);
以下代码在Eclipse IDE中生成编译器错误。
ArrayList<Consumer<Object>> list;
Object value;
...
list.
stream().
map(consumer -> () -> consumer.accept(value));
错误是:
Type mismatch: Can not convert from Stream<Object> to <unknown>.
The target type of this expression must be a functional interface.
如何帮助编译器将Consumer
转换为Runnable
?
以下代码修复了问题,但非常详细。
map(consumer -> (Runnable) (() -> consumer.accept(value)));
有更简洁的方法吗?我知道我可以创建一个接受Consumer
并返回Runnable
的静态方法,但我并不认为这更简洁。
答案 0 :(得分:10)
如果您考虑表达式,则错误消息是正常的:
list.stream().map(consumer -> () -> consumer.accept(value))
^--------------------------^
what is the type of that?
问题是编译器无法确定表达式() -> consumer.accept(value)
的目标类型。它当然可以是Runnable
,但也可以{:1}}声明:
MyAwesomeInterface
实际上,它可以符合声明功能方法不带参数且不返回任何值的任何功能接口。因此,这会导致编译错误。
使用:
在@FunctionalInterface
interface MyAwesomeInterface { void foo(); }
中显式存储lambda表达式时没有错误
Runnable
因为,然后编译器知道该lambda的目标类型是Runnable runnable = () -> consumer.accept(value);
。
当你考虑时,问题更加模糊:
Runnable
有人可能会争辩说,编译器可能能够将该表达式的目标类型推断为List<Runnable> runnables = list.stream()
.map(consumer -> () -> consumer.accept(value))
.collect(Collectors.toList());
,因为我们将其收集到Runnable
列表中。但是,it doesn't并且您必须帮助编译器稍微明确地告诉编译器Runnable
元素是Stream
:
Runnable