Lambda表達式是Java中更簡潔的匿名函數寫法,用于簡化函數式接口的實現。其標準形式包括:1. 無參數無返回值;2. 一個參數無返回值;3. 多個參數無返回值;4. 無參數有返回值;5. 一個參數有返回值;6. 多個參數有返回值。lambda可訪問外部final或effectively final變量,但不能修改它們。方法引用是lambda的簡化形式,包括靜態方法引用、實例方法引用、對象方法引用和構造方法引用。與匿名內部類相比,lambda表達式中的this指向外部類,編譯方式更高效,類型推斷依賴上下文。掌握lambda表達式能提升代碼簡潔性和可讀性,但也需合理使用以避免過度簡化影響理解。
Lambda表達式,本質上就是一種更簡潔的匿名函數寫法,讓代碼更緊湊。掌握它的標準寫法,能讓你的Java代碼瞬間提升一個檔次。
Lambda表達式主要用于簡化匿名內部類的使用,尤其是在函數式接口的場景下。它允許你將函數作為方法的參數傳遞,或者將代碼像數據一樣處理。
// 傳統方式:匿名內部類 Runnable runnable = new Runnable() { @Override public void run() { System.out.println("Hello from Runnable!"); } }; // Lambda表達式:更簡潔的寫法 Runnable lambdaRunnable = () -> System.out.println("Hello from Lambda!"); lambdaRunnable.run();
什么是函數式接口?
函數式接口是只包含一個抽象方法的接口。@functionalInterface 注解可以用來標記一個接口是函數式接口,但這并不是必須的。常見的函數式接口包括 Runnable, Callable, Predicate, Function, Consumer, Supplier 等。
立即學習“Java免費學習筆記(深入)”;
@FunctionalInterface interface MyFunctionalInterface { int myMethod(int a, int b); } MyFunctionalInterface add = (x, y) -> x + y; System.out.println(add.myMethod(5, 3)); // 輸出 8
Lambda表達式的幾種寫法
Lambda表達式的語法主要有以下幾種形式:
- 無參數,無返回值: () -> System.out.println(“Hello”);
- 一個參數,無返回值: (x) -> System.out.println(x); 或者更簡潔的 x -> System.out.println(x);
- 多個參數,無返回值: (x, y) -> System.out.println(x + y);
- 無參數,有返回值: () -> “Hello”;
- 一個參數,有返回值: (x) -> x * x; 或者 x -> x * x;
- 多個參數,有返回值: (x, y) -> x * y;
如果Lambda表達式的主體包含多條語句,需要用花括號 {} 包裹,并且如果有返回值,需要使用 return 語句。
MyFunctionalInterface subtract = (x, y) -> { int result = x - y; return result; }; System.out.println(subtract.myMethod(10, 4)); // 輸出 6
Lambda表達式如何訪問外部變量?
Lambda表達式可以訪問外部的 final 或 effectively final 變量。所謂 effectively final 變量,指的是雖然沒有顯式聲明為 final,但在初始化后沒有被修改過的變量。
int number = 5; // effectively final MyFunctionalInterface multiply = (x, y) -> x * y * number; System.out.println(multiply.myMethod(2, 3)); // 輸出 30
如果嘗試修改外部變量,編譯器會報錯。
int number = 5; // 錯誤:Variable used in lambda expression should be final or effectively final // MyFunctionalInterface incrementAndMultiply = (x, y) -> x * y * ++number;
方法引用是什么?如何使用?
方法引用是Lambda表達式的一種簡化寫法,當Lambda表達式只是調用一個現有的方法時,可以使用方法引用。方法引用有四種形式:
- 靜態方法引用: class::staticMethod
- 實例方法引用: instance::instanceMethod
- 對象方法引用: Class::instanceMethod (使用對象調用實例方法)
- 構造方法引用: Class::new
// 靜態方法引用 List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); numbers.forEach(System.out::println); // 等價于 numbers.forEach(x -> System.out.println(x)); // 實例方法引用 String str = "Hello"; Predicate<String> startsWithH = str::startsWith; // 等價于 s -> str.startsWith(s) System.out.println(startsWithH.test("Hello")); // 輸出 true // 對象方法引用 List<String> strings = Arrays.asList("a", "b", "A", "B"); strings.sort(String::compareToIgnoreCase); // 等價于 strings.sort((s1, s2) -> s1.compareToIgnoreCase(s2)); System.out.println(strings); // 輸出 [a, A, b, B] // 構造方法引用 Supplier<List<String>> listSupplier = ArrayList::new; // 等價于 () -> new ArrayList<>() List<String> newList = listSupplier.get();
Lambda表達式與匿名內部類的區別?
雖然Lambda表達式在很多情況下可以替代匿名內部類,但它們之間存在一些關鍵區別:
- this關鍵字: 在匿名內部類中,this 關鍵字指向匿名內部類的實例;而在Lambda表達式中,this 關鍵字指向的是包含Lambda表達式的外部類的實例。
- 編譯方式: 匿名內部類會被編譯成一個單獨的 .class 文件;而Lambda表達式在運行時會使用 invokedynamic 指令進行動態編譯,通常更高效。
- 類型推斷: Lambda表達式的類型推斷依賴于上下文,編譯器會根據目標類型自動推斷參數類型;而匿名內部類需要顯式聲明類型。
掌握Lambda表達式,能讓你的Java代碼更簡潔、更易讀。但也要注意合理使用,避免過度使用導致代碼可讀性下降。