Java8————方法引用
譯者注:本篇博客翻譯自Oracle官方教程《Method References》。作為Java 8 新特性Lambda表達式的引申概念,博主依然采用官方文檔的方式來學習這一重要的概念。希望對各位同道有所幫助。
方法引用
使用Lambda表達式創建匿名方法。但是,有時候Lambda表達式什么都沒做,僅僅是調用了一個已經存在的方法。這種情況下,引用已存在方法的方法名通常是更清晰的。方法引用允許你這么做,它是一種簡潔的、可讀性強的有名方法的Lambda表達式。
再次思考我們在Lambda 表達式部分(即上一篇翻譯《Java8————Lambda表達式(二)》)中討論的Person類:
public class Person {public enum Sex {MALE, FEMALE}String name;LocalDate birthday;Sex gender;String emailAddress;public int getAge() {// ...}public Calendar getBirthday() {return birthday;} public static int compareByAge(Person a, Person b) {return a.birthday.compareTo(b.birthday);}}假設你的應用中的成員全都包含在一個數組中,并且你希望把他們以年齡進行排序。你可以使用下面的代碼:
Person[] rosterAsArray = roster.toArray(new Person[roster.size()]);class PersonAgeComparator implements Comparator<Person> {public int compare(Person a, Person b) {return a.getBirthday().compareTo(b.getBirthday());} }Arrays.sort(rosterAsArray, new PersonAgeComparator());調用的sort方法的方法簽名(譯者注:方法簽名是包含方法名、參數列表等在內的方法信息)如下:
static <T> void sort(T[] a, Comparator<? super T> c)注意,Comparator接口是一個函數接口。因此,你可以使用Lambda表達式而不是去定義并隨后創建一個實現了Comparator的類的實例:
Arrays.sort(rosterAsArray,(Person a, Person b) -> {return a.getBirthday().compareTo(b.getBirthday());} );但是,比較兩個Person對象生日的方法已經存在于Person.compareByAge方法當中。你可以Lambda表達式的body中調用:
Arrays.sort(rosterAsArray,(a, b) -> Person.compareByAge(a, b) );因為這個Lambda表達式調用一個存在的方法,因此,你可以使用方法引用來代替Lambda表達式:
Arrays.sort(rosterAsArray, Person::compareByAge);方法引用 Person::compareByAge語義上與Lambda表達式(a, b) -> Person.compareByAge(a, b) 是一樣的。都具備以下特性:
1、它的參數列表:(Person , Person)從Comparator<Person>.compare復制過來。
2、它的主體調用方法Person.compareByAge()
方法引用的種類
有如下四種方法引用:
| Reference to a static method | ContainingClass::staticMethodName |
| Reference to an instance method of a particular object | containingObject::instanceMethodName |
| Reference to an instance method of an arbitrary object of a particular type | ContainingType::methodName |
| Reference to a constructor | ClassName::new |
-
靜態方法引用
方法引用如:Person::compareByAge 就是對靜態方法的引用。
-
特定對象的實例方法引用
下面的例子就是對特定對象的實例方法引用:
class ComparisonProvider {public int compareByName(Person a, Person b) {return a.getName().compareTo(b.getName());}public int compareByAge(Person a, Person b) {return a.getBirthday().compareTo(b.getBirthday());} } ComparisonProvider myComparisonProvider = new ComparisonProvider(); Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);方法引用:myComparisonProvider::compareByName,調用了myComparisonProvider對象的方法compareByName。JRE會推斷出方法的參數類型,這個例子中是(Person, Person)。
-
特定類型的任意對象的實例方法引用
下面的例子是特定類型的任意對象的實例方法引用:
String[] stringArray = { "Barbara", "James", "Mary", "John","Patricia", "Robert", "Michael", "Linda" }; Arrays.sort(stringArray, String::compareToIgnoreCase);與Lambda表達式等價的方法引用 String::compareToIgnoreCase 有一個正式的參數列表:(String a, String b), a 和b 都是用來更好的描述這個例子的任意的名稱。這個方法引用會調用方法:a.compareToIgnoreCase(b)。
-
構造器的方法引用
你可以像使用靜態方法引用的方式那樣使用new關鍵字來引用構造器。下面的方法將元素從一個集合中拷貝到另一個集合中。
public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>>DEST transferElements(SOURCE sourceCollection,Supplier<DEST> collectionFactory) {DEST result = collectionFactory.get();for (T t : sourceCollection) {result.add(t);}return result; }函數接口Supplier包含一個沒有參數并且返回一個對象的方法get()。因此,你可以像下面這樣,通過Lambda表達式調用transferElements()方法:
Set<Person> rosterSetLambda =transferElements(roster, () -> { return new HashSet<>(); });你可以像下面這樣使用構造器引用來取代Lambda表達式:
Set<Person> rosterSet = transferElements(roster, HashSet::new);Java編譯器會推斷出你希望創建一個包含元素類型為Person的HashSet集合。你可以像下面這樣來指定,二選一。
Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new);?
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Java8————方法引用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: XML学习(二)————属性还是标签?
- 下一篇: Java 多线程 —— wait 与 n