城市就是森林,每个男人都是猎人,每个女人都是陷阱。——《三体》哪里用到了Lambda表达式?上一篇文章(传送门)介绍了Lambda表达式的基本语法,给出了一个Lambda表达式的例子,就是根据品牌对口罩列表进行排序:maskList.sort((Masko1,??Masko2)->o1.getBrand().compareTo(o2.getBrand()));这里使用的sort方法的参数类型是Comparator,我们将Lambda表达式作为Comparator传入sort方法。Comparator是一个函数式接口,那么什么是函数式接口呢?函数式接口函数式接口是具有一个且只有一个抽象方法的接口。上面提到的Comparator接口虽然有很多默认方法,但是它只有一个抽象方法compare,所以它仍然是一个函数式接口。再举个例子:packagejava.util.concurrent;@FunctionalInterfacepublicinterfaceCallable{Vcall()throwsException;}Callable接口只有一个call抽象方法,所以也是一个函数式接口。你可能已经发现,在Callable接口上有一个注解@FunctionalInterface,用来标记该接口是函数式接口。如果写的接口不是函数式接口,加上@FunctionalInterface注解,编译时会报错,需要注意。看完以上例子,你是不是撸起袖子准备大干一场呢?别着急,为了检验真知灼见,我们先来做个简单的测试。以下三个接口中,哪些是函数式接口,哪些不是函数式接口?Runnablepackagejava.lang;@FunctionalInterfacepublicinterfaceRunnable{publicabstractvoidrun();}Taskpackagecom.sun.jmx.snmp.tasks;publicinterfaceTaskextendsRunnable{publicvoidcancel();}Serializablepackagejava.io;publicinterfaceSerializable{}请想一想...公布答案:Runnable只有一个抽象方法run,所以功能接口Task有两个抽象方法,分别是自己的cancel方法和继承自Runnable的run方法。所以不是一个功能接口。Serializable没有任何方法,因此它不是函数式接口。这个怎么样?你没事儿吧?实现函数式接口了解了什么是函数式接口之后,我们可以直接使用Lambda表达式来为函数式接口提供实现,也可以将整个Lambda表达式作为一个函数式接口的实例。比如上面提到的Runnable接口,我们直接这样赋值:Runnablerunnable=()->{System.out.println("万猫学社");};至此,我们知道了Lambda表达式的公式在哪里使用,那么如何正确使用Lambda表达式呢?如何使用Lambda表达式?从上面Runnable接口实例的例子可以看出,Runnable接口的run方法没有入参,也没有返回,该方法的签名为()->void;Lambda表达式同样没有输入参数,也不返回,表达式的签名为()->void。也就是说:函数式接口的抽象方法的签名必须和Lambda表达式的签名一致。再举个例子,在口罩列表按品牌排序的例子中,Comparator接口的compare方法的签名是(T,T)->int,Lambda表达式的签名也是(T,T)->整数。为了加深理解,我们来做个小测试,看看哪些代码正确使用了Lambda表达式?CallableCallablecallable=()->{return"万茂学院";};RunnableRunnablerunnable=()->{return"万茂学院";};ComparatormaskList.sort((Masko1,Masko2)->{if(o1.getBrand().equals(o2.getBrand())){returno1.getType().compareTo(o2.getType());}else{returno1.getBrand().compareTo(o2.getBrand());}});请想一想……公布答案:Callable:正确,Lambda表达式的签名为()->String,与Callable接口唯一抽象方法调用的签名匹配,所以是正确的。Runnable:Error,Lambda表达式的签名是()->String,但是Runnable接口唯一抽象方法run的签名是()->void,两者不匹配,所以是错误的。Comparator:正确,Lambda表达式的签名为(Mask,Mask)->int,与Comparator接口唯一抽象方法compare的签名匹配,所以正确。这个怎么样?你没事儿吧?综上所述,只有一个抽象方法的接口称为函数式接口,Lambda表达式可以直接作为函数式接口的实例。函数式接口抽象方法的签名必须与Lambda表达式的签名一致。