Lambda表達式是java8的新特性,沒用過的人可能會對它比較抵觸,用過的人呢又爲之癡迷。在Lambda表達式中,有個很重要的用法是簡化某些匿名類,咱們經過下面的例子來感覺一下。java
有個老婆婆有一隻雞天天都要生蛋,她天天都要給雞蛋記上生產日期
1.7及以前的寫法以下:
定義一個標記雞蛋的接口MarkEgg:express
public interface MarkEgg { void mark(); }
而後用匿名類調用,記錄10天老婆婆的動做。ide
public class OldLady { public static void main(String[] args) { for (int i = 0; i < 10; i++) { mark(new MarkEgg() { @Override public void mark() { System.out.println("今天的雞蛋"); } }); } } public static void mark(MarkEgg markEgg) { markEgg.mark(); } }
咱們能夠看到,雖然匿名類省略了類名,可是仍是不夠簡潔的。咱們看看用Lambda是怎麼簡化代碼的。函數
public class OldLady { public static void main(String[] args) { for (int i = 0; i < 10; i++) { mark(() -> System.out.println("今天的雞蛋")); } } public static void mark(MarkEgg markEgg) { markEgg.mark(); } }
另外,在MarkEgg接口上,要標記@FunctionalInterface
,這個註解表示,這個接口是函數式接口,若是咱們標記了@FunctionalInterface
,但它卻不是函數式接口,編譯器就會報錯,可是不寫也是能夠的,如同@Override
。spa
@FunctionalInterface public interface MarkEgg { void mark(); }
下面對比一下兩個主體部分:
Lambda表達式有三個部分:
第一個是參數列表,對應圖中的1
,這裏例子沒有參數。
第二個是->
,把參數和Lambda主體分開。
第三個是Lambda主體,對應上面的輸出語句2
。code
老婆婆並不會寫字,因此她讓別人代寫,只須要跟別人說在雞蛋寫什麼
MarkEgg接口簡單的改一下:orm
@FunctionalInterface public interface MarkEgg { String mark(); }
OldLady類:blog
public class OldLady { public static void main(String[] args) { for (int i = 0; i < 10; i++) { mark(() -> "今天的雞蛋"); } } public static void mark(MarkEgg markEgg) { System.out.println(markEgg.mark()); } }
注意一下,Lambda主體中,並無return。接口
此時,別人跟老婆婆說,你每次都寫今天,你之後怎麼知道是哪天的,因此你要告訴我是哪天。
MarkEgg接口加上參數:編譯器
@FunctionalInterface public interface MarkEgg { String mark(int day); }
OldLady類:
public class OldLady { public static void main(String[] args) { for (int i = 0; i < 10; i++) { mark((int day) -> String.format("第%s天的雞蛋", day), i + 1); } for (int i = 0; i < 10; i++) { mark(day -> String.format("第%s天的雞蛋", day), i + 1); } } public static void mark(MarkEgg markEgg, int day) { System.out.println(markEgg.mark(day)); } }
咱們上面參數,有兩個形式,第一個是(int day)
,第二個直接是day
,把參數類型去掉。
Lambda的基本語法是
(parameters) -> expression
或(咱們上面都是單行的,若是是多行,就要加大括號,且若是是有返回值要加return
)
(parameters) -> { statements; }