因為 Java lambda expression 語法,需要有一種語法,可以引用 method,但不直接呼叫該 method。Method Reference 就是利用 :: 雙冒號,讓 Java 可以做到這件事。
Method Reference 有四種
Kind | Syntax | Examples |
---|---|---|
參考 class 的 static method | *ContainingClass*::*staticMethodName* |
Person::compareByAge MethodReferencesExamples::appendStrings |
參考一個 object instance 的 method | *containingObject*::*instanceMethodName* |
myComparisonProvider::compareByName myApp::appendStrings2 |
參考特定類別,任意物件的 instance method | *ContainingType*::*methodName* |
String::compareToIgnoreCase String::concat |
參考 constructor | *ClassName*::new |
HashSet::new |
物件比較範例
首先定義一個 Person.java data class
import java.util.Date;
public class Person {
private String name;
private int age;
private Date birthday;
public static int compareByAge(Person a, Person b) {
return a.birthday.compareTo(b.birthday);
}
public Person(String name, int age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public Date getBirthday() {
return birthday;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", birthday=" + birthday +
'}';
}
}
傳統的物件比較,會用 comparator 來實作。目前可以進化改用 lambda expression,或是 method reference
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.Locale;
import java.util.stream.Stream;
public class PersonExample {
public static Person[] newArray() {
try {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
Person a = new Person("A", 10, formatter.parse("2014-02-01"));
Person b = new Person("B", 20, formatter.parse("2004-03-01"));
Person[] rosterAsArray = {a, b};
return rosterAsArray;
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
public static void test1_comparator() {
Person[] rosterAsArray = newArray();
// 定義 Comparator
class PersonAgeComparator implements Comparator<Person> {
public int compare(Person a, Person b) {
return a.getBirthday().compareTo(b.getBirthday());
}
}
Arrays.sort(rosterAsArray, new PersonAgeComparator());
Stream.of(rosterAsArray).forEach(System.out::println);
System.out.println("");
}
public static void test2_lambda() {
Person[] rosterAsArray = newArray();
// 使用 lambda expression
Arrays.sort(rosterAsArray,
(Person p1, Person p2) -> {
return p1.getBirthday().compareTo(p2.getBirthday());
}
);
Stream.of(rosterAsArray).forEach(System.out::println);
System.out.println("");
}
public static void test3_static_method() {
Person[] rosterAsArray = newArray();
// 使用 Person 裡面已經定義的 static method
Arrays.sort(rosterAsArray,
(p3, p4) -> Person.compareByAge(p3, p4)
);
Stream.of(rosterAsArray).forEach(System.out::println);
System.out.println("");
}
public static void test4_static_method_reference() {
Person[] rosterAsArray = newArray();
// 使用 Person 裡面已經定義的 static method reference
Arrays.sort(rosterAsArray, Person::compareByAge);
Stream.of(rosterAsArray).forEach(System.out::println);
System.out.println("");
}
public static void main(String... args) {
test1_comparator();
test2_lambda();
test3_static_method();
test4_static_method_reference();
}
}
MethodReference 測試
以下例子利用上面的前三種 Method Reference 方式,列印 "Hello World!",第一個是直接使用 lambda expression 實作。
import java.util.function.BiFunction;
public class MethodReferencesExamples {
public static <T> T mergeThings(T a, T b, BiFunction<T, T, T> merger) {
return merger.apply(a, b);
}
public static String appendStrings(String a, String b) {
return a + b;
}
public String appendStrings2(String a, String b) {
return a + b;
}
public static void main(String[] args) {
MethodReferencesExamples myApp = new MethodReferencesExamples();
// Calling the method mergeThings with a lambda expression
// 以 lambda expression 呼叫 mergeThings
System.out.println(MethodReferencesExamples.
mergeThings("Hello ", "World!", (a, b) -> a + b));
// Reference to a static method
// static method 的 Method Reference
System.out.println(MethodReferencesExamples.
mergeThings("Hello ", "World!", MethodReferencesExamples::appendStrings));
// Reference to an instance method of a particular object
// 參考一個 object instance 的 method
System.out.println(MethodReferencesExamples.
mergeThings("Hello ", "World!", myApp::appendStrings2));
// Reference to an instance method of an arbitrary object of a
// particular type
// 參考特定類別,任意物件的 instance method
System.out.println(MethodReferencesExamples.
mergeThings("Hello ", "World!", String::concat));
}
}