Lambda Expressions in Java 8
Lambda 表示式是 Java 8 最流行的特性。它們將函數語言程式設計概念引入 Java,這是一種完全物件導向的指令式程式設計語言。 函數語言程式設計語言的工作原理超出了本文的範圍,但我們將提取一個特性,該特性對於使用 OOP 的我們來說是顯而易見的。
在這篇文章中,我們將瞭解 lambda 表示式到底是什麼以及它們如何融入整個 Java 生態系統。 我們還將檢視不使用 lambda 表示式的示例程式碼,然後重構此程式碼以使用 lambda。
理解一個Lambda表示式
Lambda 表示式是我們可以傳遞執行的程式碼塊。 將程式碼塊傳遞給函式是我們作為 Java 程式設計師不習慣的事情。 我們所有的行為定義程式碼都封裝在方法體中,並通過物件引用執行,就像使用以下程式碼一樣:
public class LambdaDemo {
public void printSomething(String something) {
System.out.println(something);
}
public static void main(String[] args) {
LambdaDemo demo = new LambdaDemo();
String something = "I am learning Lambda";
demo.printSomething(something);
}
}
這是對呼叫者隱藏方法實現的經典 OOP 風格。 呼叫者只需將一個變數傳遞給該方法,然後該方法對變數的值執行一些操作並返回另一個值或產生副作用,就像在我們的例子中一樣。
我們現在將看到一個等效的實現,它使用行為傳遞而不是變數傳遞。 為了實現這一點,我們必須建立一個函式式介面來定義抽象行為而不是方法。 功能介面是隻有一個方法的介面:
public class LambdaDemo {
interface Printer {
void print(String val);
}
public void printSomething(String something, Printer printer) {
printer.print(something);
}
}
在上面的實現中,Printer
介面負責所有的列印。 printSomething
方法不再定義行為,而是執行由 Printer
定義的行為:
public static void main(String[] args) {
LambdaDemo demo = new LambdaDemo();
String something = "I am using a Functional interface";
Printer printer = new Printer() {
@Override
public void print(String val) {
System.out.println(val);
}
};
demo.printSomething(something, printer);
}
你們中的細心的人可能已經注意到我們在這裡沒有做任何新的事情。 這是真的,因為我們還沒有應用 lambda 表示式。 我們簡單地建立了 Printer
介面的具體實現並將其傳遞給 printSomething
方法。
上面的演示旨在將我們帶到在 Java 中引入 Lambda 表示式的關鍵目標:Lambda 表示式主要用於定義功能介面的內聯實現。
在我們使用 lambda 表示式重構上面的例子之前,讓我們學習必要的語法:
(param1,param2,param3...,paramN) - > {//block of code;}
一個 lambda 構成一個用括號括起來的逗號分隔的形式引數列表,就像我們在方法宣告中定義的那樣,後跟一個指向要執行的程式碼的箭頭標記。 現在讓我們重構上面的程式碼以使用 lambda:
public static void main(String[] args) {
LambdaDemo demo = new LambdaDemo();
String something = "I am learning Lambda";
/**/
Printer printer = (String toPrint)->{System.out.println(toPrint);};
/**/
demo.printSomething(something, printer);
}
非常緊湊和美觀。 由於函式式介面只宣告瞭一個方法,因此在 lambda 的第一部分中傳遞的引數會自動對映到方法的引數列表中,並且箭頭右側的程式碼被視為方法的具體實現
為什麼要使用Lambda表示式
與上一節中的演示一樣,lambda 表示式使我們能夠擁有更緊湊的程式碼,更易於閱讀和遵循。 在效能和多核處理方面還有其他好處,但只有在瞭解 Streams API 後才能理解,因此超出了本文的範圍。
比較使用和不使用 lambda 的主要方法實現肯定向我們展示了 lambda 表示式在縮短程式碼方面的強大功能:
public static void main(String[] args) {
LambdaDemo demo = new LambdaDemo();
String something = "I am learning Lambda";
/**/
Printer printer = (String toPrint)->{System.out.println(toPrint);};
/**/
demo.printSomething(something, printer);
}
我們可以讓我們的程式碼比這更簡潔。 碰巧的是,即使沒有在箭頭左側指定引數的型別,編譯器也會從介面方法的形式引數中推斷出它的型別:
Printer printer = (toPrint)->{System.out.println(toPrint);};
我們仍然可以做得更好。 lambda 的另一個特點是:如果只有一個引數,我們可以完全去掉括號。 同樣,如果箭頭右邊只有一個語句,我們也可以去掉大括號:
Printer printer = toPrint -> System.out.println(toPrint);
現在我們的程式碼真的開始看起來很可愛了。 我們才剛剛開始。 如果我們的介面方法不帶任何引數,我們可以用空括號替換宣告:
() -> System.out.println("anything");
不如我們直接內聯 lambda,而不先建立一個物件,然後將它傳遞給 saySomething 方法:
public static void main(String[] args) {
LambdaDemo demo = new LambdaDemo();
String something="I am Lambda";
/**/
demo.printSomething(something, toPrint -> System.out.println(toPrint));
}
現在我們真的開始談論函數語言程式設計了。 我們最初的九行主體現在減少到只有 3 行。 這種程式碼的緊湊性使得 lambda 表示式對 Java 程式設計師非常有吸引力。