java8新特性lambda表达式

时间:2021-05-02 18:45:43

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.


package com.jelly.java8.lambda;


public interface MyRunnable {
   
public void run();
}


接着是MyThread类,它的构造函数中需要接收一个MyRunnable 接口类型的对象。

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

jdk8 的写法:

@Test
public void test1(){
new MyThread(()->System.out.println("hello...")).start();
   
}



是的,lambda表达式就是这么用的,简单吧。反过来看,大家以后只要看到能够使用lambda的场合,那么接口必定也是只含有一个抽象方法。

比如集合排序需要传入comparator接口,你可以手动new一个comparator比较器,再实现compare方法,当然也可以使用lambda表达式。

你会发现lambda表达式就是匿名接口实现的语法糖!!! 哈哈答对了,java中的语法糖其实还真不少,泛型、枚举、增强for都是。



好了,说了这么多...额,似乎忘了介绍lambda的语法了。

lambda表达式中间有个标志性的箭头符号 ->

箭头的左边是一个以逗号分隔的形参列表,用小括号包起来。形参可以不指定其java类型(lambda表达式可以根据上下文自行推断)。

如果形参只有一个,那么小括号也可省略。如果没有形参,则左边保留一对小括号()即可。

箭头右边可以是一个表达式或一个java代码块。 如果是代码块,则必须用一对大括号{}包起来,其中可以包含多条java语句,每条语句以分号结尾。

如果lambda表达式函数需要返回值,则需要在代码块最后执行return 语句。如果是一个表达式,那么无须用大括号{}包起来,也无须用分号结束。

需要特别注意的是:lambda的右边如果是只有一个表达式,则无须return这个表达式。lambda会执行这个表达式,并将表达式运算的结果自动返回。