在我的情况下,我有一个消费者接受? extends String
的供应商并对其执行某些操作,因此声明如下:
final Consumer<? super Supplier<? extends String>> action = ...
问题是当我尝试执行操作时,编译器看起来并不高兴,并且会出现以下错误:
此表达式的目标类型必须是功能接口
在我的情况下,我有一个名字的客户,所以以下行触发了这个错误:
action.accept(customer::getName)
我的假设是? super Supplier<? extends String>
不再被视为功能界面,因为它是一种捕获类型。
那么,有人可以就这种情况给我一个明确的解释吗?
答案 0 :(得分:3)
为什么使用此令牌? super Supplier
。那是什么意思?您只需传递Supplier
,即@FunctionalInterface
。试试这个,
public class MyConsumer implements Consumer<Supplier<String>> {
@Override
public void accept(Supplier<String> t) {
System.out.println(t.get());
}
public static void main(String[] args) {
MyConsumer myConsumer = new MyConsumer();
myConsumer.accept(() -> "Test");
}
}
@FunctionalInterface
注释对于代码的编译时间检查很有用。你不能有多种方法。对于Runnable
实例,Callable
是适合此的实例。
但是你可以进一步压缩它:
Consumer<Supplier<String>> myConsumer = (Supplier<String> supplier) -> System.out.println(supplier.get());
myConsumer.accept(() -> "Test");
由于编译器可以推断出类型,因此将进一步简化为
Consumer<Supplier<String>> myConsumer = supplier -> System.out.println(supplier.get());
myConsumer.accept(() -> "Test");
答案 1 :(得分:1)
这只是类型推断中的一个缺陷。请注意,而
final Consumer<? super Supplier<? extends String>> action=s -> System.out.println(s.get());
action.accept(() -> "foo");
因编译错误而失败
final Consumer<? super Supplier<? extends String>> action=s -> System.out.println(s.get());
action.accept((Supplier<? extends String>)() -> "foo");
编译并运行没有问题。
也是如此final Consumer<? super Supplier<? extends String>> action=s -> System.out.println(s.get());
final Supplier<? extends String> supp = () -> "foo";
action.accept(supp);
因此,编译器根本没有为参数类型Supplier<? extends String>
推断出目标类型? super Supplier<? extends String>
。另请注意,在提供lambda表达式时,它会将Supplier<String>
推断为Supplier<? extends String>
赋值的目标类型。