Lambda表達式又稱為閉包或匿名方法,形式如下:
(int?x,?int?y)?->?x-y;
( )?->?2;
(String?s)?->?{?System.out.println(s);?};
第一個lambda表達式接收x和y這兩個整形參數并返回它們的差;第二個lambda表達式不接收任何參數,直接返回整數2;第三個lambda表達式接收一個字符串并把它打印到控制臺。
從上面的例子看,lambda表達式的語法結構和函數幾乎是一樣的,只是沒有函數名。它由參數列表、箭頭符號和函數體組成。當然函數體既可以是一個表達式,也可以是一個大括號包圍的語句塊。
從例子看,Lambda表達式語法確實相當簡潔。
那么它的意義何在呢?
Lambda表達式的意義:
對程序員來說最直觀的感受就是用Lambda表達式可以簡化很多代碼。使用它可以很輕松的將很多行代碼縮減成一行。
而更大的意義是,Lambda表達式對java性能的提升。
要理解Lambda的意義就先看看Lambda解決了Java里的什么困惑
在java和android里常會看到這種回調接口:
public interface ActionListener{
void actionPerformed(ActionEvent e);
}
使用的時候,要么我們定義一個類來實現ActionListener接口,要么使用匿名內部類。
button.addActionListener(new ActionListener(){?
public void actionPerformed(ActionEvent e)?{
ShowDialog(e.tostring());
}
})
放個概念:函數式接口:只有一個方法的接口。大多數回調接口都擁有這個特征:比如Runnable接口和Comparator接口。
這個ActionListener回調接口例子里的五行代碼中僅有一行在做實際工作。冗余代碼太多,是寫代碼層面直觀的效率感受。
同時,這種通過匿名內部類的方式也不是一個好的方案。匿名內部類存在著影響應用性能的問題。
對于匿名內部類,編譯器會為每一個匿名內部類創建相應的類文件。一般的程序,往往回調接口會有很多。這樣就會生成很多的類文件,因為類在使用之前需要加載類文件并進行驗證,這個過程就會影響應用的性能。
然后,java就引入Lambda表達式了。上面那個例子,用Lambda表達式后變成如下:
button.addActionListener((ActionEvent e) -> ShowDialog(e.tostring()));
明顯代碼簡潔很多。
在這種情況下,編譯器會負責推導這個lambda表達式具體是對應哪個函數式接口類型。注意:lambda表達式只能出現在目標類型為函數式接口的上下文中。
這是Lambda表達式在代碼簡潔方面的意義。
在效率提升方面的意義是通過把函數式接口的匿名內部類方法的調用改成類靜態方法調用來完成的。
編譯器在將Lambda表達式轉成函數式接口實例時,分析這個方法體是否需要變量捕獲(Lambda方法體需要訪問外部變量時則為需變量捕獲,反之則為變量不捕獲)。對于無需變量捕獲的Lambda,其方法體會被提取到一個靜態方法中,這個靜態方法和Lambda表達式位于同一個類中。對于需要變量捕獲的Lambda表達式情況有點復雜,最后也會把Lambda表達式提取到一個靜態方法中。也就是Lambda表達式雖然推導到相應的函數式接口,但并沒有編譯成匿名內部類的方式來處理,而做成是直接方法調用。
然后就是,在大多數情況下,Lambda表達式要比匿名內部類性能更優。