问题描述:
使用Java8 Stream对数组进行排序
list.stream().sorted(Comparator.comparing(SeriesData::getName));
其中
sorted()
函数需要传入一个Comparator,而我们使用了Comparator中的静态方法comparing()
构建了一个Comparator。在构建Comparator的时候comparing()
需要传入一个函数的引用作为参数,也就是SeriesData::getName
。
SeriesData类如下:
public class SeriesData {
private Object name;
public void setName(Object name) {
this.name = name;
}
public Object getName() {
return name;
}
}
这时出现两个错误:
Error:(343, 86) java: no suitable method found for comparing(SeriesData::getName)
method java.util.Comparator.<T,U>comparing(java.util.function.Function<? super T,? extends U>,java.util.Comparator<? super U>) is not applicable
(cannot infer type-variable(s) T,U
(actual and formal argument lists differ in length))
method java.util.Comparator.<T,U>comparing(java.util.function.Function<? super T,? extends U>) is not applicable
(inferred type does not conform to upper bound(s)
inferred: java.lang.Object
upper bound(s): java.lang.Comparable<? super java.lang.Object>,java.lang.Object)
Error:(343, 97) java: invalid method reference
non-static method getName() cannot be referenced from a static context
Q1
第一个错误就是说,向comparing()
方法中传入的参数类型是错的。为什么是错的呢?
首先先来看看comparing()
这个函数的实现:
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
第一眼:WTF!,这是什么鬼,根本看不懂啊,那就赶紧好好补补课!
首先这是一个静态方法,其次,这是泛型方法。
static后面的
<T, U extends Comparable<? super U>>
,这是泛型方法的泛型参数声明部分,意思是:方法中有一种没有任何限制的参数类型T,另一种参数是实现了Comparable<? super U>接口的类U。comparing()
方法接受一个参数:Function<? super T, ? extends U> keyExtractor
,这是一个函数引用,所引用的函数需要传入一个参数T,并返回一个U或他的子类。
这是要注意U是如何限定的:实现了Comparable<? super U>接口的类
而在上面的程序中的引用方法SeriesData::getName
,返回的是Object
,很遗憾它没有实现Comparable
接口,所以也就出现了第一个错误。
Q2
第二个错误看似很好理解:“静态上下文中无法引用非静态方法无法”,getName
是一个非静态的方法,而comparing()
则是静态的,这导致问题无可厚非。But,很怪异的是,当我把getName
的返回值改为String
后就不会出现上述的问题了,找了好久没找到原因。
另外,也尝试了其他例子,只要是在静态方式中使用非静态方法都会出现“non-static method cannot be referenced”这个错误。
public static Integer fun2(String a) {
System.out.println(a);
return Integer.valueOf(a);
}
public static void fun1(Function<String, Integer> ac) {
Stream.of("1", "2", "4").map(x -> ac.apply("1"));
}
public static void main(String[] args) {
fun1(StorageAreaAction::fun2);
}
如果把fun2()
中的static
去掉则会报错。
猜测: 难道是因为setter
方法的原因?
如果有哪位大神知道的话还请不吝赐教。