簡單地說,就是一個Lambda表達式。在Java 8中,我們會使用Lambda表達式創建匿名方法,但是有時候,我們的Lambda表達式可能僅僅調用一個已存在的方法,而不做任何其它事,對於這種情況,通過一個方法名字來引用這個已存在的方法會更加清晰,Java 8的方法引用允許我們這樣做。方法引用是一個更加緊湊,易讀的Lambda表達式,注意方法引用是一個Lambda表達式,其中方法引用的操作符是雙冒號"::"。
先看一個例子
首先定義一個Person類,如下:
package methodreferences;
import java.time.LocalDate;
public class Person
{
public Person(String name, LocalDate birthday)
{
this.name = name;
this.birthday = birthday;
}
String name;
LocalDate birthday;
public LocalDate getBirthday()
{
return birthday;
}
public static int compareByAge(Person a, Person b)
{
return a.birthday.compareTo(b.birthday);
}
@Override
public String toString()
{
return this.name;
}
}
假設我們有一個Person數組,並且想對它進行排序,這時候,我們可能會這樣寫:
package methodreferences;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Comparator;
public class Main
{
static class PersonAgeComparator implements Comparator<Person> {
public int compare(Person a, Person b) {
return a.getBirthday().compareTo(b.getBirthday());
}
}
public static void main(String[] args)
{
Person[] pArr = new Person[]{
new Person("003", LocalDate.of(2016,9,1)),
new Person("001", LocalDate.of(2016,2,1)),
new Person("002", LocalDate.of(2016,3,1)),
new Person("004", LocalDate.of(2016,12,1))};
Arrays.sort(pArr, new PersonAgeComparator());
System.out.println(Arrays.asList(pArr));
}
}
其中,Arrays類的sort方法定義如下:
public static <T> void sort(T[] a, Comparator<? super T> c)
這裡,我們首先要注意Comparator接口是一個函數式接口,因此我們可以使用Lambda表達式,而不需要定義一個實現Comparator接口的類,並創建它的實例對象,傳給sort方法。
使用Lambda表達式,我們可以這樣寫:
package methodreferences;
import java.time.LocalDate;
import java.util.Arrays;
public class Main
{
public static void main(String[] args)
{
Person[] pArr = new Person[]{
new Person("003", LocalDate.of(2016,9,1)),
new Person("001", LocalDate.of(2016,2,1)),
new Person("002", LocalDate.of(2016,3,1)),
new Person("004", LocalDate.of(2016,12,1))};
Arrays.sort(pArr, (Person a, Person b) -> {
return a.getBirthday().compareTo(b.getBirthday());
});
System.out.println(Arrays.asList(pArr));
}
}
然而,在以上代碼中,關於兩個人生日的比較方法在Person類中已經定義了,因此,我們可以直接使用已存在的Person.compareByAge方法。
package methodreferences;
import java.time.LocalDate;
import java.util.Arrays;
public class Main
{
public static void main(String[] args)
{
Person[] pArr = new Person[]{
new Person("003", LocalDate.of(2016,9,1)),
new Person("001", LocalDate.of(2016,2,1)),
new Person("002", LocalDate.of(2016,3,1)),
new Person("004", LocalDate.of(2016,12,1))};
Arrays.sort(pArr, (a, b) -> Person.compareByAge(a, b));
System.out.println(Arrays.asList(pArr));
}
}
因為這個Lambda表達式調用了一個已存在的方法,因此,我們可以直接使用方法引用來替代這個Lambda表達式,
package methodreferences;
import java.time.LocalDate;
import java.util.Arrays;
public class Main
{
public static void main(String[] args)
{
Person[] pArr = new Person[]{
new Person("003", LocalDate.of(2016,9,1)),
new Person("001", LocalDate.of(2016,2,1)),
new Person("002", LocalDate.of(2016,3,1)),
new Person("004", LocalDate.of(2016,12,1))};
Arrays.sort(pArr, Person::compareByAge);
System.out.println(Arrays.asList(pArr));
}
}
在以上代碼中,方法引用Person::compareByAge在語義上與Lambda表達式 (a, b) -> Person.compareByAge(a, b) 是等同的,都有如下特性:
我們前面舉的例子Person::compareByAge就是一個靜態方法引用。
如下示例,引用的方法是myComparisonProvider 對象的compareByName方法;
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);
如下示例,這裡引用的是字符串數組中任意一個對象的compareToIgnoreCase方法。
String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);
如下示例,這裡使用了關鍵字new,創建了一個包含Person元素的集合。
Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new);
transferElements方法的定義如下,功能為集合拷貝,
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;
}
當一個Lambda表達式調用了一個已存在的方法
當我們需要往引用的方法傳其它參數的時候,不適合,如下示例:
IsReferable demo = () -> ReferenceDemo.commonMethod("Argument in method.");
http://java8.in/java-8-method-references/
https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html