Java8,有界通配符类型不被视为功能接口

时间:2018-04-20 10:07:16

标签: java java-8 functional-interface bounded-wildcard

在我的情况下,我有一个消费者接受? extends String的供应商并对其执行某些操作,因此声明如下:

final Consumer<? super Supplier<? extends String>> action = ...

问题是当我尝试执行操作时,编译器看起来并不高兴,并且会出现以下错误:

  

此表达式的目标类型必须是功能接口

在我的情况下,我有一个名字的客户,所以以下行触发了这个错误:

action.accept(customer::getName)

我的假设是? super Supplier<? extends String>不再被视为功能界面,因为它是一种捕获类型。

那么,有人可以就这种情况给我一个明确的解释吗?

2 个答案:

答案 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>赋值的目标类型。