方法引用(Method Reference) 上一篇中記錄了Lambda表達式,其可以創建匿名方法。當Lambda表達式只是調用一個存在的方法時,可以採用方法引用(JDK8具有的特性)。如下: 假設需要對一組人員按年齡進行排序,可以採用下邊的方式,將人員數組與實現的比較器,傳遞給Array.sort ...
方法引用(Method Reference)
上一篇中記錄了Lambda表達式,其可以創建匿名方法。當Lambda表達式只是調用一個存在的方法時,可以採用方法引用(JDK8具有的特性)。如下:
1 public class Person { 2 3 public enum Sex { 4 MALE, FEMALE 5 } 6 7 String name; 8 LocalDate birthday; 9 Sex gender; 10 String emailAddress; 11 int age; 12 13 public int getAge() { 14 return age; 15 } 16 17 public LocalDate getBirthday() { 18 return birthday; 19 } 20 21 public static int compareByAge(Person a, Person b) { 22 return a.birthday.compareTo(b.birthday); 23 } 24 }
假設需要對一組人員按年齡進行排序,可以採用下邊的方式,將人員數組與實現的比較器,傳遞給Array.sort方法:
1 Person[] rosterAsArray = roster.toArray(new Person[roster.size()]); 2 3 class PersonAgeComparator implements Comparator<Person> { 4 public int compare(Person a, Person b) { 5 return a.getBirthday().compareTo(b.getBirthday()); 6 } 7 } 8 9 Arrays.sort(rosterAsArray, new PersonAgeComparator());
當然,可以將PersonAgeComparator的實現採用Lambda表達式,如下:
1 Arrays.sort(rosterAsArray, (a,b) -> a.birthday.compareTo(b.birthday));
Person類中已經包含根據年齡的比較compareByAge,只需要在Lambda表達式體中直接調用即可:
1 Arrays.sort( rosterAsArray, (a,b) -> Person.compareByAge(a,b));
由於Lambda表達式調用一個已經存在的方法,可以使用方法引用代替Lambda表達式,如下:
1 Arrays.sort(rosterAsArray, Person::compareByAge);
其中 ,Person::compareByAge 與 (a, b) -> Person.compareByAge(a, b)是等價的。(1)其參數拷貝於Comparator<Person>.compare,即 (Person, Person);(2)body將調用Person.compareByAge。
方法引用類別
有4種方法引用,如下:
- 引用靜態方法,如 ContainingClass::staticMethodName;
- 引用實例方法,如 containingObject::instanceMethodName;
- 引用特殊類型對象的方法,如 ContainingType::methodName;
- 引用構造函數,如 ClassName::new。
(1)引用靜態方法
上文中的例子即為靜態方法引用。
(2)引用實例方法
即通過類的實例引用方法,如下:
1 class ComparisonProvider { 2 public int compareByName(Person a, Person b) { 3 return a.getName().compareTo(b.getName()); 4 } 5 6 public int compareByAge(Person a, Person b) { 7 return a.getBirthday().compareTo(b.getBirthday()); 8 } 9 } 10 ComparisonProvider myComparisonProvider = new ComparisonProvider(); 11 Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);
(3)引用特殊類型對象的方法
以String為例:
1 String[] stringArray = { "Barbara", "James", "Mary", "John", 2 "Patricia", "Robert", "Michael", "Linda" }; 3 Arrays.sort(stringArray, String::compareToIgnoreCase);
(4)引用構造函數
假設transferElements實現從一個集合到另一個集合拷貝元素,如下:
1 public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>> 2 DEST transferElements( 3 SOURCE sourceCollection, 4 Supplier<DEST> collectionFactory) { 5 6 DEST result = collectionFactory.get(); 7 for (T t : sourceCollection) { 8 result.add(t); 9 } 10 return result; 11 }
其中Supplier包含一個get方法,只返回一個空的集合對象,並且不需要任何參數,可以使用Lambda表達式實現,如下:
1 Set<Person> rosterSetLambda = 2 transferElements(roster, () -> { return new HashSet<>(); });
此時可以採用引用構造函數的方法,如下:
Set<Person> rosterSet = transferElements(roster, HashSet::new); //或 Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new);
總結
- 對於Lambda表達式,當只是調用一個已存在的方法時,可以採用方法引用的方式實現,編譯器會自行翻譯
參考