Java 8 之前,傳遞行為參數主要靠匿名內部類:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Running in thread");
}
}).start();
這帶來三大問題:
final 或實際上 final 的局部變量this 指向自身而非外部類函數式接口:有且僅有一個抽象方法的接口。常見例子:Runnable、Callable、Comparator、ActionListener。可用 @FunctionalInterface 註解標記(編譯器會強制檢查)。
(參數列表) -> { 方法體 }
// 或表達式形式(單行,隱式返回)
(參數列表) -> 表達式
示例:
(String s) -> s.length() // 單參數,表達式體
() -> 43 // 無參,返回常量
(int x, int y) -> x + y // 多參數,表達式體
(String s) -> { // 語句塊體,需显式 return
System.out.println(s);
return s.length();
}
Comparator<String> c = (s1, s2) -> s1.compareToIgnoreCase(s2);ActionListener listener = e -> System.out.println(e.getWhen());returnLambda 允許捕獲實際上 final的局部變量(無需显式 final),且不允許聲明同名變量遮蓋外部變量:
public void lambdaExample() {
String variable = "Method Local";
String nonFinalVariable = "Non-final"; // 未修改,實際上 final
new Thread(() -> {
// String variable = "Shadow"; // 編譯錯誤:不允許遮蓋
System.out.println(variable); // 捕獲外部變量
System.out.println(this.variable); // this 指向外部類實例
}).start();
}
語法:類名::靜態方法、對象::實例方法、類名::實例方法、類名::new(構造器引用)。
// 靜態方法引用
Arrays.sort(employees, Employee::myCompare);
// 實例方法引用(特定對象)
list.forEach(System.out::println);
// 任意對象實例方法引用
list.sort(String::compareToIgnoreCase);
// 構造器引用
Supplier<List<String>> supplier = ArrayList::new;
Function<String, Employee> creator = Employee::new;
編譯器根據目標類型自動匹配重載方法。
Java 8 允許接口定義默認實現:
interface MyInterface {
void normalMethod();
default void defaultMethod() {
System.out.println("Default implementation");
}
}
解決菱形繼承衝突規則:
InterfaceName.super.method()Lambda 表達式、方法引用、默認方法構成了 Java 8 函數式編程的三大支柱。它們不僅解決了匿名類的語法冗長和語義限制,更為 Stream API、CompletableFuture 等現代 Java 特性奠定了基礎。掌握閉包機制,是寫出簡潔、表達力強的現代 Java 代碼的關鍵。