Lambda 表達式的語法
本節我們將介紹 Lambda 表達式的語法,了解 Lambda 表達式的基本形式和幾種變體,以及編譯器是怎么理解我們的 Lambda 表達式的。
掌握了這些基礎的知識,我們就能很容易的辨別出 Lambda 表達式,以及它是怎么運作的。
1. 基本語法
現在我們來回顧下第一 個 Lambda 表達式的例子:
button.addActionListener(event -> System.out.println("button click"));
這是一個最基本的 Lambda 表達式,它由三部分組成具體格式是這樣子的:
參數 -> 具體實現
包含一個 Lambda 表達式的運算符 ->
,在運算符的左邊是輸入參數,右邊則是函數主體。
概括來講就是:
Tips: 一段帶有輸入參數的可執行語句塊
Lambda 表達式有這么幾個特點:
- 可選類型聲明: 不需要聲明參數類型,編譯器可以自動識別參數類型和參數值。在我們第一個例子中,并沒有指定 event 到底是什么類型;
- 可選的參數圓括號: 一個參數可以不用定義圓括號,但多個參數需要定義圓括號;
- 可選的大括號: 如果函數主體只包含一個語句,就不需要使用大括號;
- 可選的返回關鍵字: 如果主體只有一個表達式返回值則編譯器會自動返回值,大括號需要指明表達式返回了一個數值。
這幾個特點是不是看著有點暈呢?不要緊,你只要知道除了我們第一個例子中的 Lambda 表達式的基本形式之外,這些特點還能夠形成它的幾種變體。接下來我們來看下一個 Lambda 表達式的一些變體。
2. Lambda 表達式的五種形式
2.1 不包含參數
Runnable noArguments = () -> System.out.println("hello world");
在這個例子中,Runnable 接口,只有一個 run 方法,沒有參數,且返回類型為 void,所以我們的 Lambda 表達式使用 ()
表示沒有輸入參數。
2.2 有且只有一個參數
ActionListener oneArguments = event -> System.out.println("hello world");
在只有一個參數的情況下 我們可以把 ()
省略。
2.3 有多個參數
BinaryOperator<Long> add = (x,y) -> x+y ;
使用 ()
把參數包裹起來,并用 ,
來分割參數。上面的代碼表示。
2.4 表達式主體是一個代碼塊
Runnable noArguments = () -> {
System.out.print("hello");
System.out.println("world");
}
當有多行代碼的時候我們需要使用 {}
把表達式主體給包裹起來。
2.5 顯示聲明參數類型
BinaryOperator<Long> add = (Long x, Long y) -> x+y ;
通常 Lambda 的參數類型都有編譯器推斷得出的,也可以顯示的聲明參數類型。
3. 關于 Lambda 表達式的參數類型
我們再來看一下 2.3 的例子:
BinaryOperator<Long> add = (x,y) -> x+y ;
在這個例子中,參數 x
,y
和返回值 x+y
我們都沒有指定具體的類型,但是編譯器卻知道它是什么類型。原因就在于編譯器可以從程序的上下文推斷出來,這里的上下文包含下面 3 種情況:
- 賦值上下文;
- 方法調用上下文;
- 類型轉換上下文。
通過這 3 種上下文就可以推斷出 Lambda 表達式的目標類型。
目標類型并不是一個全新的概念,通常我們在 Java 數據初始化的時候就是根據上下文推斷出來的。比如:
String[] array = {"hello","world"};
等號右邊的代碼我們并沒有聲明它是什么類型,系統會根據上下文推斷出類型的信息。
4. 小結

本節主要介紹了:
- Lambda 表達式的基本語法及其幾種變體形式。
- 在 Lambda 表達式中,編譯器會根據程序的上下文自動推斷出目表達式的目標類型。
掌握這些知識可以幫助我們快速的辨別一個 Lambda 表達式,方便的去理解程序的意圖。