是否可以将方法引用与接口的静态方法一起使用?

时间:2018-10-10 19:46:52

标签: java lambda method-reference

这是我的第一个代码:

public class MethodReference {
    public static void main (String []args) {
        Stream<String> s = Stream.of("brown bear", "grizzly");
        s.sorted(Comparator.reverseOrder()).forEach(System.out::print);
        //...
    }
}

结果:灰熊棕熊

这是我的第二个代码:

public class MethodReference {
    public static void main (String []args) {
        Stream<String> s = Stream.of("brown bear", "grizzly");
        s.sorted(Comparator::reverseOrder()).forEach(System.out::print);
        //...
    }
}

结果:编译器错误

我的问题: 为什么第二个代码中出现编译器错误? 我不能将方法参考用于功能接口的静态方法吗?

我知道我不能在功能接口的默认方法中使用方法引用。 我知道我可以在5种情况下对类使用方法引用:

班级

  • Class :: staticMethod

  • Class :: instanceMethod

  • instance :: instanceMethod

  • Class :: new

功能界面

  • Interface :: abstractMethod

非常感谢!

2 个答案:

答案 0 :(得分:6)

Comparator.reverseOrder()是一个可解析为Comparator类型的表达式,因为它就是返回的内容。

Comparator::reverseOrder是一个表达式,它解析为方法,该方法不包含任何参数并返回一个Comparator,例如Supplier<Comparator<String>>,尽管它可以是任何匹配的功能接口。

在第二个实例中,您尝试传递方法(提供Comparator)作为参数。该方法不需要-仅需要Comparator本身。

您可以这样想(只是伪代码来说明这一点):

s.sorted(new Comparator())

vs

s.sorted(new Supplier(new Comparator()))

要回答第二个问题,即是否有可能对接口的静态方法使用方法引用-是的,绝对可以!

如果我们声明以下方法:

<T> void giveMeAComparatorSupplier(Supplier<Comparator<T>> supplier) { }

那么我们绝对可以使用方法引用来调用它

giveMeAComparatorSupplier(Comparator::reverseOrder);

(仅供参考,您的方法引用语法错误-它从不使用()

答案 1 :(得分:3)

您的第二个代码有两件事是错误的。首先,方法引用根本不使用括号或参数。您只需要提供稍后将要调用的方法即可。您此时不会调用该方法。

第二,sorted方法使用Comparator,而不是提供Comparator的功能接口。该方法需要已经创建并准备就绪的Comparator,而不是需要时提供Comparator的功能接口。

Comparator是一个接口与它无关;人们通常可以创建对static接口方法的方法引用。它与sorted需要实际的Comparator实例而不是功能接口的实例这一事实有关,在这种情况下,您可以提供方法引用。

因此,即使删除括号,它也不会编译。只有直接通过Comparator的第一个代码才能按预期进行编译和工作。