这是我的第一个代码:
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
功能界面
非常感谢!
答案 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
的第一个代码才能按预期进行编译和工作。