# 方法參照
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` `方法參照`