您能否解释为什么第一个未包装的方法引用无法编译?

时间:2019-02-25 14:29:19

标签: java java-8 java-stream method-reference

在此示例中,将方法引用传递给Stream.of不起作用,但是一旦被包装,它便起作用。我不太明白为什么会这样。方法引用不等同于功能接口吗?

public class A {

    String a() {
        return "";
    }

    void b() {
        Stream.of(this::a); // won't compile
        Stream.of(wrap(this::a)); // will compile
    }

    static <T> Supplier<T> wrap(Supplier<T> f) {
        return f;
    }
}

3 个答案:

答案 0 :(得分:1)

Stream.of(T)需要一个Object,并且您在第一条语句中将方法引用传递给它。但是Object参数不是功能接口,因此它不能接受方法引用或未明确键入的lambda。
使用lambda时,也会产生错误:Stream.of(()->this.a())
一个更简单的示例可以是Stream.of(()-> "foo"),它将不会编译。

但是,如果您输入方法引用或lambda,它将起作用:

Stream.of((Supplier<String>) this::a)

Stream.of((Supplier<String>) () -> this.a())

在工作语句中,您将Stream.of(T)的参数传递给Supplier<String>。这是指功能接口,但其输入方式与前面的工作示例相同,因此它作为期望Object的参数有效。

答案 1 :(得分:1)

Stream.of具有以下签名:

public static<T> Stream<T> of(T t)

将编译以下示例,因为您为T显式提供了类型信息。

Stream<Supplier<String>> a = Stream.of(this::a);

第一个示例Stream.of(this::a);等效于:

Object a = this::a;

其中Object不是功能接口,因此不会编译。

此示例通过功能界面进行编译:

Runnable a = this::a;
Stream.of(a);

在第二个示例中,wrap提供了功能接口Supplier

答案 2 :(得分:1)

this::a是无上下文的,可能意味着不同的含义。您需要提供一些上下文,以帮助编译器弄清楚this::a的实际含义。

Stream.<Supplier<String>>of(this::a);

尽管如此,Stream<Supplier<String>>似乎并不是您想要的。如果您需要Stream<String>,请使用Stream.generate:由于该方法采用了Supplier<T>(此处没有歧义),因此不需要额外的类型信息。

Stream.generate(this::a);

另一方面,两条语句都希望您将结果保存到变量中。定义正确类型的变量通常有助于解决此类问题。

Stream<Supplier<String>> s1 = Stream.of(this::a);
Stream<String> s2 = Stream.generate(this::a);

感谢@ J-Alex和@Holger的宝贵评论。