5

我正在尝试将 a 转换ConsumerRunnable. 以下代码不会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.

如何帮助编译器将 a 转换Consumer为 a Runnable

下面的代码解决了这个问题,但非常冗长。

map(consumer -> (Runnable) (() -> consumer.accept(value)));

有没有更简洁的方法来做到这一点?我知道我可以创建一个接受 aConsumer并返回 a的静态方法Runnable,但我不认为这更简洁。

4

1 回答 1

13

如果您考虑以下表达式,则错误消息是正常的:

list.stream().map(consumer -> () -> consumer.accept(value))
                              ^--------------------------^
                                what is the type of that?

问题是编译器无法确定表达式的目标类型() -> consumer.accept(value)。当然可以Runnable,但也可以MyAwesomeInterface声明为:

@FunctionalInterface
interface MyAwesomeInterface { void foo(); }

事实上,它可以符合任何声明一个不带参数且不返回值的函数式方法的函数式接口。因此,这会导致编译错误。

将 lambda 表达式显式存储在 with 中时没有错误Runnable

Runnable runnable = () -> consumer.accept(value);

因为,然后编译器知道该 lambda 的目标类型是Runnable.


当您考虑以下问题时,问题会更加模糊:

List<Runnable> runnables = list.stream()
                               .map(consumer -> () -> consumer.accept(value))
                               .collect(Collectors.toList());

有人可能会争辩说,编译器可能能够推断出该表达式的目标类型,Runnable因为我们将其收集到Runnable. 但是,它没有,你必须帮助编译器并明确告诉编译器Stream元素是Runnable

List<Runnable> runnables = list.stream()
                               .<Runnable> map(consumer -> () -> consumer.accept(value))
                               .collect(Collectors.toList());
于 2016-02-18T19:04:36.633 回答