Java 8中方法也是一種對象,可以By名字來引用。不過方法引用的唯一用途是支持Lambda的簡寫,使用方法名稱來表示Lambda。不能通過方法引用來獲得諸如方法簽名的相關信息。
方法引用的分類
方法引用分爲4類,常用的是前兩種。方法引用也受到訪問控制權限的限制,可以通過在引用位置是否能夠調用被引用方法來判斷。具體分類信息如下:
引用靜態方法
ContainingClass::staticMethodName
例子: String::valueOf,對應的Lambda:(s) -> String.valueOf(s)
比較容易理解,和靜態方法調用相比,只是把.換爲::引用特定對象的實例方法
containingObject::instanceMethodName
例子: x::toString,對應的Lambda:() -> this.toString()
與引用靜態方法相比,都換爲實例的而已引用特定類型的任意對象的實例方法
ContainingType::methodName
例子: String::toString,對應的Lambda:(s) -> s.toString()
太難以理解了。難以理解的東西,也難以維護。建議還是不要用該種方法引用。
實例方法要通過對象來調用,方法引用對應Lambda,Lambda的第一個參數會成爲調用實例方法的對象。引用構造函數
ClassName::new
例子: String::new,對應的Lambda:() -> new String()
構造函數本質上是靜態方法,只是方法名字比較特殊。
方法引用的例子
public class MethodReference {
public static void main(String[] args) {
// 方法引用::引用構造函數
PersonFactory factory = new PersonFactory(Person::new);
List<Person> personList = new ArrayList<Person>();
Person p1 = factory.getPerson();
p1.setName("Kobe");
personList.add(p1);
Person p2 = factory.getPerson();
p2.setName("James");
personList.add(p2);
Person p3 = factory.getPerson();
p3.setName("Paul");
personList.add(p3);
Person[] persons1 = personList.toArray(new Person[personList.size()]);
System.out.print("排序前: ");
printArray(persons1);
// 方法引用::引用靜態方法
Arrays.sort(persons1, MethodReference::myCompare);
System.out.print("排序後: ");
printArray(persons1);
System.out.println();
Person[] persons2 = personList.toArray(new Person[personList.size()]);
System.out.print("排序前: ");
printArray(persons2);
// 方法引用::用特定對象的實例方法
Arrays.sort(persons2, p1::compare);
System.out.print("排序後: ");
printArray(persons2);
System.out.println();
Person[] persons3 = personList.toArray(new Person[personList.size()]);
System.out.print("排序前: ");
printArray(persons3);
// 方法引用::引用特定類型的任意對象的實例方法
Arrays.sort(persons3, Person::compareTo);
System.out.print("排序後: ");
printArray(persons3);
}
public static void printArray(Person[] persons) {
for (Person p : persons) {
System.out.print(p.name + " ");
}
System.out.println();
}
public static int myCompare(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
static class Person {
private String name;
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int compare(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
public int compareTo(Person p) {
return this.getName().compareTo(p.getName());
}
}
static class PersonFactory {
private Supplier<Person> supplier;
public PersonFactory(Supplier<Person> supplier) {
this.supplier = supplier;
}
public Person getPerson() {
return supplier.get();
}
}
}
結語
方法引用僅僅是Lambda的配套服務,主要目的是通過名字來獲得Lambda,重複利用已有的方法。