Java 8 for Android: Lambda Expressions
Lambda Expressions 是能夠有效幫助我們簡化程式碼的方法之一,在現今支援 Java 8 的 Android Studio 中,即便不去使用,也必須要懂得閱讀。
Lambda 算是 Java 8 重大新功能之一,基本上從 Android Studio 3 開始就可以被支援使用,不只是在用在 Java 開發上,Kotlin 開發也會用到大量的 Lambda。
在原本需要實作匿名類 (Anonymous Class) 的設計上,使用 Lambda 表達式去取代,能夠讓程式碼更為簡潔,但實際上 Lambda 表示一個獨立的 function,並不屬於任何一個 class,可以將其理解為可傳遞的匿名函數,沒有名稱,但有參數列表、函數主體、回傳類型。
(argument) -> {expression}
這個便是最基本的 Lambda 語法表示。
參數 Argument
會是由一個或者多個參數所組成,必須由括號括起來,即便沒有參數的也得保留括號:
() -> doSomething();
這是一個參數的情況:
(int parameter) -> doSomething();
在參數類型能夠被自動推導之下,可省略宣告部分,單一參數可省略括號:
parameter -> doSomething();
這是多個參數的情況,我們使用逗號去分開不同參數,而因為能夠被自動推導型態,宣告部分也得以省略:
(int parameter1, int parameter2) -> doSomething();(parameter1, parameter2) -> doSomething(); //
表達式 Expression
表達式內部放的就是需要執行的程式碼,我們以大括號將其括起來,另外在單個表達式的狀況下,可以將大括號省略:
(parameter1, parameter2) -> {
doSomething();
doNothing();}(parameter1, parameter2) -> doSomething(); // Single expression
是不是很好奇為什麼我們可以這樣做呢?其實上面的情況都有一個共通點,就是被固定的類型都只有 一個接口 ,而因為只有一個接口,便可以被自動推導,進而讓我們簡化程式碼,另外有 return 值的話也可以省略掉 return、括號、分號。下面 Example 2 的 Comparator 雖然不只一個方法,但其只有 compare 是必須被實作的,所以也能符合 Lambda 的使用情境。
Lambda 表達後也可將其作為變數使用:
其實 Java 8 還有另外一個特性,Lambda 表達式內可以直接使用外部的變數,不用像以前一樣,得先將外部的變數宣告為 final 後才得以使用,雖然方便但還是有限制,就是這邊不會允許對外部變數做修改。
另外值得一提的是,在之前的匿名類型方法設計之下,OnClickListenr 內部的 this 會是 OnClickListener 本身,但在 Lambda 表達式下,在表達式內部所用到的 this,其實還會是外部的 this,以下面的範例來看,就是 Activity 對象本身。
方法引用 Method References
ClassName::MethodClassName::staticMethod
對於在 Lambda 表達式內使用方法,也是能夠在經由推導後,簡化不少程式碼,下面展示一下逐步推導的過程:
/* Lambda basic */
(a, b) -> a.compareTo(b)/* 推導 Step1: compareTo 是 Integer 的方法。 */
(a, b) -> Integer.compareTo(b)/* 推導 Step2: 因為參數有順序,省略括號及 b。 */
(a, b) -> Integer.compareTo/* 推導 Step3: 因為沒有用到參數,都省略掉。 */
Integer.compareTo/* 推導 Step4: 為了區分改為使用 :: 表示。 */
Integer::compareTo
建構方法引用 Constructor Method References
ClassName::new
這個建構方法引用也跟 Method References 屬於同一類,只是在後面的表示變成 new,用來表示創建新對象,這邊以 Java 8 的範例來說明。
現在在使用 Android Studio 開發的時候,如果有能夠被置換成 Lambda 表達式的地方,都會標記成灰色做為提醒,而使用這個功能的前提,只要記得在 module 的 build.gradle 去設定 compileOptions,就能成功地做好支援 Java 8 環境的設定:
android {
compileSdkVersion 28
... ignored... compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
結論
這次就為大家介紹 Lambda 到這邊,稍微展示了使用 Lambda 是如何讓程式碼做到簡化的,有沒有獲得一些心得呢?不妨從現在開始,試著與 Lambda 做個接觸吧!
Balus