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; }