# 方法參照 Lambda 表示式實作的匿名方法包含三部分 : 1. 方法參數(argument list)。 2. 箭頭符號(arrow token),為`->` 3. 方法內容(body)。 方法內容(body)只是呼叫另一個方法(method),可將此改寫為「方法參照(method reference)」,讓語法更簡潔。 ## 四種方法內容 依據被呼叫的方法的種類和來源,可分為以下四種 : 1. 方法是靜態(static),來自某類別。 2. 方法是實例(instance),來自 lambda 之「外」的參考變數。 3. 方法是實例(instance),來自 lambda 之「內」的參考變數。 4. 使用`new`呼叫建構子。 ## 範例 實作 Arrays 類別的 sort 方法,所用的參數`Comparator<? super T> c` ### 靜態方法 ```java= class Utility1 { static int comparatorImp1(String s1, String s2) { return s1.compareToIgnoreCase(s2); } } ``` ```java= String[] strings = {"a", "b", "c", "d", "e"}; // Arrays.sort(strings, (a, b) -> Utility1.comparatorImp1(a, b)); Arrays.sort(strings, Utility1::comparatorImp1) ``` ### lambda 之「外」的參考變數 ```java= class Utility2 { int comparatorImp2(String s1, String s2) { return s1.compareToIgnoreCase(s2); } } ``` ```java= String[] strings = {"a", "b", "c", "d", "e"}; Utility2 u2 = new Utility2(); // Arrays.sort(strings, (s1, s2) -> u2.comparatorImp2(s1, s2)); Arrays.sort(strings, u2::comparatorImp2); ``` ### lambda 之「內」的參考變數 ```java= String[] strings = {"a", "b", "c", "d", "e"}; Utility2 u2 = new Utility2(); // Arrays.sort(strings, (s1, s2) -> s1.compareToIgnoreCase(s2)); Arrays.sort(strings, String::compareToIgnoreCase); ``` > 參考來自 lambda 表示式內與靜態方法很像,都是用類別名稱。可藉由方法是否為 static 區分。 > 本例來說,String 類別的 compareToIgnoreCase() 方法非 static 方法,所以為內部參數的實例方法。 ### 使用`new`呼叫建構子 `ClassName::new` ```java= public class MethodReferenceDemo { String x; public MethodReferenceDemo() {} public MethodReferenceDemo(String s) { this.x = s; } public void printX() { System.out.println(x); } private static MethodReferenceDemo createWithoutInput() { // Supplier<MethodReferenceDemo> supplier = () -> new MethodReferenceDemo(); Supplier<MethodReferenceDemo> supplier = MethodReferenceDemo::new; return supplier.get(); } private static MethodReferenceDemo createWithInput() { // Function<String, MethodReferenceDemo> function = s -> new MethodReferenceDemo(s); Function<String, MethodReferenceDemo> function = MethodReferenceDemo::new; return function.apply("inputValue"); } public static void main(String[] args) { createWithoutInput(); createWithInput().printX(); } ``` > 使用方法參照呼叫建構子時,語法上是使用無參數的 Supplier 介面。若要產生需要參數的建構子,須改用 function 介面。 > 若參數超過兩個,則先定義符合該個數的 FunctionalInterface。 ```java=27 public MethodReferenceDemo(String x, Integer y, Double z) { this.x = y + z + x; } @FunctionalInterface private interface FunctionDemo<One, Two, Three, Four> { public Four apply(One one, Two two, Three three); } private static MethodReferenceDemo test() { FunctionDemo<String, Integer, Double, MethodReferenceDemo> function = MethodReferenceDemo::new; return function.apply("", 0, 0.0); } } ``` ###### tags: `Java` `method reference` `方法參照`