jdk8于2014年3月正式发布,至今已有3年余。然而对大多数程序员而言,jdk8还是比较陌生的,相信大多数人在公司最常用的还是jdk7吧。废话不多说了,我们本篇就来学习下java8中新特性——lambda表达式。
第一个lambda的示例: new 线程
before jdk8,我们需要手动new一个接口,并实现其中唯一的一个抽象方法。
@Test
public void test(){
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello world...");
}
}).start();
}
现在我们使用jdk8,可以有更简单的写法:
@Test
public void test2(){
new Thread(
()->{System.out.println("hello world...");
System.out.println("haha..");}
).start();
}
lambda表达式的作用似乎已经明朗了:为简化书写,用表达式替代匿名内部类。
是的,实际上对于所有的只含有一个抽象方法的接口,我们都可以用lambda表达式表示。我们可以简单地理解为这里的lambda表达式就是这个接口的一种实现的一个实例对象。函数是一个对象?是的,这听起来似乎不可思议,当实际上很多函数式编程语言就是这么干的,比如大家熟知的JavaScript,函数其实就是Function对象。好吧,我们扯远了,还是回到java。
那么我们自己写的类/接口,能否使用到lambda表达式呢? 当然可以,只要这个接口只含有一个抽象方法,我们可大胆地使用lambda。 我们将上面的例子用自己写的类/接口重现一下。
首先是MyRunnable接口,它只含一个抽象方法run.
public interface MyRunnable {
public void run();
}
package com.jelly.java8.lambda;
public interface MyRunnable {
public void run();
}
before jdk8
@Test
public void test1(){
new MyThread(new MyRunnable() {
@Override
public void run() {
System.out.println("hello...");
}
}).start();
}
@Test
public void test1(){
new MyThread(()->System.out.println("hello...")).start();
}
是的,lambda表达式就是这么用的,简单吧。反过来看,大家以后只要看到能够使用lambda的场合,那么接口必定也是只含有一个抽象方法。
比如集合排序需要传入comparator接口,你可以手动new一个comparator比较器,再实现compare方法,当然也可以使用lambda表达式。
你会发现lambda表达式就是匿名接口实现的语法糖!!! 哈哈答对了,java中的语法糖其实还真不少,泛型、枚举、增强for都是。
lambda表达式中间有个标志性的箭头符号 ->
箭头的左边是一个以逗号分隔的形参列表,用小括号包起来。形参可以不指定其java类型(lambda表达式可以根据上下文自行推断)。
如果形参只有一个,那么小括号也可省略。如果没有形参,则左边保留一对小括号()即可。
箭头右边可以是一个表达式或一个java代码块。 如果是代码块,则必须用一对大括号{}包起来,其中可以包含多条java语句,每条语句以分号结尾。
如果lambda表达式函数需要返回值,则需要在代码块最后执行return 语句。如果是一个表达式,那么无须用大括号{}包起来,也无须用分号结束。
需要特别注意的是:lambda的右边如果是只有一个表达式,则无须return这个表达式。lambda会执行这个表达式,并将表达式运算的结果自动返回。