如何在 Java 中將方法作為參數傳遞
一、簡介
在 Java 中,我們可以使用函數式程式設計概念,特別是使用 lambda 表達式、方法參考和函數式接口,將一個方法作為參數傳遞給另一個方法。在本教程中,我們將探索幾種將方法作為參數傳遞的方法。
2.使用介面和匿名內部類
在 Java 8 之前,我們依賴介面和匿名內部類別來將方法作為參數傳遞。下面是一個例子來說明這種方法:
interface Operation {
int execute(int a, int b);
}
我們使用單一抽象方法execute()
定義一個名為Operation
的介面。此方法接受兩個整數作為參數並傳回一個整數。任何實作此介面的類別都必須提供execute()
方法的實作。
接下來,我們建立一個名為performOperation()
的方法來接受兩個整數參數和一個Operation
實例:
int performOperation(int a, int b, Operation operation) {
return operation.execute(a, b);
}
在這個方法中,我們呼叫operation.execute(a, b)
。這行程式碼呼叫作為參數傳遞的Operation
實例的execute()
方法。
然後我們呼叫performOperation()
方法並傳入三個參數:
int actualResult = performOperation(5, 3, new Operation() {
@Override
public int execute(int a, int b) {
return a + b;
}
});
在performOperation()
方法內部,使用匿名內部類別建立Operation
介面的新實例。類別沒有名稱,但它動態提供了execute()
方法的實作。
在匿名內部類別中, execute()
方法被重寫。在本例中,它只是將兩個整數a
和b
相加,並傳回兩個整數的和。
最後,讓我們使用斷言來驗證我們的實現,以確保結果符合預期:
assertEquals(8, actualResult);
3. 使用 Lambda 表達式
在 Java 8 中,lambda 表達式使得將方法作為參數傳遞更加優雅和簡潔。以下是我們如何使用 lambda 實現相同的功能:
@FunctionalInterface
interface Operation {
int execute(int a, int b);
}
我們定義一個介面Operation
,並使用@FunctionalInterface
註解來表示這個介面只有一個抽象方法。
接下來,我們呼叫performOperation()
方法並傳入兩個整數參數和一個Operation
介面的實例:
int actualResult = performOperation(5, 3, (a, b) -> a + b);
對於第三個參數,我們傳遞一個 lambda 表達式(a, b) -> a + b
,而不是匿名內部類,它表示Operation
函數介面的實例。
我們應該得到相同的結果:
assertEquals(8, actualResult);
與匿名內部類別相比,使用 lambda 表達式可以簡化語法並使程式碼更具可讀性。
4. 使用方法引用
Java 中的方法引用提供了一種將方法作為參數傳遞的簡化方法。它們充當調用特定方法的 lambda 表達式的簡寫。讓我們看看如何使用方法引用來實現相同的功能。
我們定義一個名為add()
的方法,它接受兩個整數a
和b
作為參數並傳回它們的和:
int add(int a, int b) {
return a + b;
}
此方法只是將兩個整數相加並傳回結果。然後,使用語法object::methodName
或ClassName::methodName
將該方法作為參考傳遞:
int actualResult = performOperation(5, 3, FunctionParameter::add);
assertEquals(8, actualResult);
這裡, FunctionParameter::add
指的是FunctionParameter
類別中的add()
方法。它允許我們將add()
方法定義的行為作為參數傳遞給另一個方法,在本例中performOperation()
方法。
此外,在performOperation()
方法中, add()
方法引用被視為Operation
功能介面的實例,該介面具有單一抽象方法execute()
。
5. 使用Function
類
除了方法引用和 lambda 表達式之外,Java 8 還引入了java.util.function
包,它為常見操作提供了函數式介面。其中, BiFunction
是一個函數式接口,表示具有兩個輸入參數和一個返回值的函數。讓我們來探討如何使用BiFunction
來實現類似的功能。
首先,我們建立一個接受BiFunction<Integer, Integer, Integer>
作為第一個參數的executeFunction()
方法。這意味著它接收一個函數,該函數接受兩個Integer
值作為輸入並傳回一個Integer
:
int executeFunction(BiFunction<Integer, Integer, Integer> function, int a, int b) {
return function.apply(a, b);
}
apply()
方法用於將函數應用到它的兩個參數。接下來,我們可以使用 lambda 表達式建立BiFunction
的實例,並將其作為參數傳遞給executeFunction()
方法:
int actualResult = executeBiFunction((a, b) -> a + b, 5, 3);
此 lambda 表達式(a, b) -> a + b
表示將其兩個輸入相加的函數。整數5
和3
分別作為第二個和第三個參數傳遞。
最後,我們使用斷言來驗證我們的實作是否如預期般運作:
assertEquals(8, actualResult );
6. 使用Callable
類
我們也可以使用Callable
將方法作為參數傳遞。 Callable
介面是java.util.concurrent
套件的一部分,表示傳回結果並可能引發異常的任務。這在並發程式設計中特別有用。
讓我們探討如何使用Callable
將方法作為參數傳遞。首先,我們建立接受Callable<Integer>
作為參數的executeCallable()
方法。這意味著它收到一個返回Integer
任務:
int executeCallable(Callable<Integer> task) throws Exception {
return task.call();
}
call()
方法用於執行任務並傳回結果。它可能會拋出異常,因此我們需要對其進行適當的處理。我們可以使用 lambda 表達式或匿名內部類別來定義Callable
任務。為簡單起見,這裡我們使用 lambda 表達式:
Callable<Integer> task = () -> 5 + 3;
此 lambda 表達式表示計算5
和3
總和的任務。然後我們可以呼叫executeCallable()
方法並將Callable
task
作為參數傳遞:
int actualResult = executeCallable(task);
assertEquals(8, actualResult);
使用Callable
將方法作為參數傳遞提供了一種替代方法,該方法在並發程式設計場景中特別有用。
七、結論
在本文中,我們探索了在 Java 中將方法作為參數傳遞的各種方法。對於簡單的操作,lambda 表達式或方法引用由於其簡潔性而通常是首選。對於複雜的操作,匿名內部類別可能仍然適合。
與往常一樣,範例的原始程式碼可在 GitHub 上取得。