Java 8 前,傳遞行為需用匿名內部類,程式碼冗長。Lambda 讓函數成為一等公民,支援函數式程式設計風格。
// 匿名內部類
Runnable r1 = new Runnable() {
@Override public void run() { System.out.println("Hello"); }
};
// Lambda 簡潔版
Runnable r2 = () -> System.out.println("Hello Lambda!");
| 形式 | 範例 | 說明 |
|---|---|---|
| 無參數 | () -> System.out.println("Hi") | () 不可省略 |
| 單參數 | x -> x * 2 或 (x) -> x * 2 | 括號可省略 |
| 多參數 | (int x, int y) -> x + y | 建議顯式宣告型別 |
| 程式碼區塊 | (x, y) -> { int z = x + y; return z; } | 需 {} 與 return |
| 型別推論 | BinaryOperator<Long> add = (x, y) -> x + y; | 編譯器自動推斷參數型別 |
僅含單一抽象方法的介面,可隱式轉換為 Lambda。JDK 內建 java.util.function 提供豐富預設介面:
Predicate<T>:boolean test(T t)Function<T,R>:R apply(T t)Consumer<T>:void accept(T t)Supplier<T>:T get()BinaryOperator<T>:T apply(T t1, T t2)@FunctionalInterface
public interface AddOperator<T, D> {
long add(T one, D two);
}
// 使用
AddOperator<Long, Long> op = (x, y) -> x + y;
System.out.println(op.add(34L, 65L)); // 99
Lambda 本身無型別,其型別由上下文(賦值目標、方法參數、回傳型別)決定,稱為「目標型別」。編譯器依此推斷參數與回傳型別。
final 或 effectively final(僅賦值一次)String name = getName(); // effectively final
button.addActionListener(e -> System.out.println(name));
// name = "new"; // 編譯錯誤:變數不再 effectively final
Lambda 的語法糖,四種形式:
ClassName::staticMethodinstance::methodClassName::methodClassName::newlist.stream().filter(...).map(...).collect(...)executor.submit(() -> doWork())button.onAction(e -> handle())掌握 Lambda 是邁向現代 Java 開發的關鍵,配合 Stream API 與 Optional 可寫出更具表達力、可維護的程式碼。