問題描述:
使用Java8 Stream對數(shù)組進(jìn)行排序
list.stream().sorted(Comparator.comparing(SeriesData::getName));
其中
sorted()
函數(shù)需要傳入一個Comparator匙隔,而我們使用了Comparator中的靜態(tài)方法comparing()
構(gòu)建了一個Comparator瑟慈。在構(gòu)建Comparator的時候comparing()
需要傳入一個函數(shù)的引用作為參數(shù),也就是SeriesData::getName
弄喘。
SeriesData類如下:
public class SeriesData {
private Object name;
public void setName(Object name) {
this.name = name;
}
public Object getName() {
return name;
}
}
這時出現(xiàn)兩個錯誤:
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()
方法中傳入的參數(shù)類型是錯的押蚤。為什么是錯的呢苞慢?
首先先來看看comparing()
這個函數(shù)的實(shí)現(xiàn):
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!,這是什么鬼风钻,根本看不懂啊顷蟀,那就趕緊好好補(bǔ)補(bǔ)課!
首先這是一個靜態(tài)方法骡技,其次鸣个,這是泛型方法。
static后面的
<T, U extends Comparable<? super U>>
布朦,這是泛型方法的泛型參數(shù)聲明部分囤萤,意思是:方法中有一種沒有任何限制的參數(shù)類型T,另一種參數(shù)是實(shí)現(xiàn)了Comparable<? super U>接口的類U是趴。comparing()
方法接受一個參數(shù):Function<? super T, ? extends U> keyExtractor
涛舍,這是一個函數(shù)引用,所引用的函數(shù)需要傳入一個參數(shù)T唆途,并返回一個U或他的子類富雅。
這是要注意U是如何限定的:實(shí)現(xiàn)了Comparable<? super U>接口的類
而在上面的程序中的引用方法SeriesData::getName
,返回的是Object
肛搬,很遺憾它沒有實(shí)現(xiàn)Comparable
接口没佑,所以也就出現(xiàn)了第一個錯誤。
Q2
第二個錯誤看似很好理解:“靜態(tài)上下文中無法引用非靜態(tài)方法無法”温赔,getName
是一個非靜態(tài)的方法蛤奢,而comparing()
則是靜態(tài)的,這導(dǎo)致問題無可厚非。But啤贩,很怪異的是待秃,當(dāng)我把getName
的返回值改為String
后就不會出現(xiàn)上述的問題了,找了好久沒找到原因痹屹。
另外章郁,也嘗試了其他例子,只要是在靜態(tài)方式中使用非靜態(tài)方法都會出現(xiàn)“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
方法的原因?
如果有哪位大神知道的話還請不吝賜教足画。