問題描述:
使用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
方法的原因?
如果有哪位大神知道的話還請不吝賜教。