我读了Java 8教程中关于Lambda表达式的部分,但是对于“特定类型的任意对象的实例方法引用”的方法引用示例还不太理解。
在同样的教程中,有一个名为“特定对象的实例方法引用”的示例,看起来是这样的:
public int compareByName(Person a, Person b) {
return a.getName().compareTo(b.getName());
}
Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);
我能看出这个方法是可行的,因为compareByName方法与Comparator.compare具有相同的签名,lambda (a, b) -> myComparisonProvider.compareByName(a, b)接收两个参数并调用一个带有相同两个参数的方法。
现在,“对特定类型任意对象的实例方法的引用”示例使用String::compareToIgnoreCase。
String[] stringArray = { "Barbara", "James", "Mary", "John",
"Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);
该方法的签名为int compareTo(String anotherString)
,与Comparator.compare不同。教程并不是很清楚,但似乎意味着您最终会得到一个lambda表达式,例如(a, b) -> a.compareToIgnoreCase(b)。我不明白编译器如何决定第二个参数对Arrays.sort是可接受的。我认为也许编译器足够智能,可以理解如何调用该方法,因此我创建了一个示例。
public class LambdaTest {
public static void main(String... args) {
String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase); // This works
// using Static methods
Arrays.sort(stringArray, FakeString::compare); // This compiles
Arrays.sort(stringArray, FakeString::compareToIgnoreCase); // This does not
// using Instance methods
LambdaTest lt = new LambdaTest();
FakeString2 fs2 = lt.new FakeString2();
Arrays.sort(stringArray, fs2::compare); // This compiles
Arrays.sort(stringArray, fs2::compareToIgnoreCase); // This does not
for(String name : stringArray){
System.out.println(name);
}
}
static class FakeString {
public static int compareToIgnoreCase(String a) {
return 0;
}
public static int compare(String a, String b) {
return String.CASE_INSENSITIVE_ORDER.compare(a, b);
}
}
class FakeString2 implements Comparator<String> {
public int compareToIgnoreCase(String a) {
return 0;
}
@Override
public int compare(String a, String b) {
return String.CASE_INSENSITIVE_ORDER.compare(a, b);
}
}
}
请问为什么上述两个 Arrays.sort 不编译,即使它们使用的方法与 String.compareToIgnoreCase 方法相同?