6.8.2 Lambda表达式与函数式接口

6.8.2 Lambda表达式与函数式接口

Lambda表达式的类型,也被称为”目标类型”(target type)”,** Lambda表达式的目标类型必须是”函数式接口(functional interface)"**。

什么是函数式接口

函数式接口就是只包含一个抽象方法的接口。函数式接口可以包含多个默认方法、类方法,但只能声明一个抽象方法。

通过匿名内部类来创建函数式接口实例

如果采用匿名内部类语法来创建函数式接口的实例,则只需要实现一个抽象方法即可。

通过Lambda表达式来创建函数式接口实例

采用Lambda表达式创建出来的对象的目标类型就是这个函数式接口的类型。

java API中的函数式接口

查询Java8API文档,可以发现大量的函数式接口,例如:RunnableActionListener等接口都是函数式接口。

函数式接口注解

Java8专门为函数式接口提供了@FunctionalInterface注解,该注解通常放在接口定义前面,该注解对程序功能没有任何作用,它用于告诉编译器执行更严格检查—检查该接口必须是函数式接口,否则编译器就会报错。

使用Lambda表示式复制

由于Lambda表达式的结果就是被当成对象,因此程序中完全可以使用Lambda表达式进行赋值。

使用Lambda表达式创建线程执行体

RunnableJava本身提供的一个函数式接口,所以可以直接使用Lambda表达式来创建Runnable实例。

1
2
3
4
5
Runnable r = () -> {
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
};

Lambda表达式的限制

Lambda表达式实现的是匿名方法—因此它只能实现特定函数式接口中的唯一方法。这意味着Lambda表达式有如下两个限制:

  1. Lambda表达式的目标类型必须是明确的函数式接口。
  2. Lambda表达式只能为函数式接口创建对象。 Lambda表达式只能实现一个方法,因此它只能为只有一个抽象方法的接口创建对象。

如何保证Lambda表达式的目标类型一定是函数式接口

为了保证Lambda表达式的目标类型是一个明确的函数式接口,可以有如下三种常见方式。

  • Lambda表达式赋值给 函数式接口类型的引用变量
  • Lambda表达式 作为函数式接口类型的参数 传给某个方法。
  • 使用函数式接口对Lambda表达式进行强制类型转换

相同的Lambda表达式的目标类型可变 只要形参列表相同即可

同样的Lambda表达式可以被当成不同的目标类型,唯一的要求是Lambda表达式的形参列表与函数式接口中唯一的抽象方法的形参列表相同

Java8预定义的函数式接口及其作用

Java8java.util.function包下预定义了大量函数式接口,典型地包含如下4类接口。

函数式接口 描述
XxxFunction 这类接口中通常包含一个apply()抽象方法,该方法对参数进行处理、转换,然后返回一个处理后的新值。该函数式接口通常用于对指定数据进行转换处理。
XxxConsumer 这类接口中通常包含一个accept()抽象方法,该方法与XxxFunction接口中的apply()方法基本相似,也负责对参数进行处理,只是该方法不会返回处理结果
XxxPredicate 这类接口中通常包含一个test()抽象方法,该方法通常用来对参数进行某种判断,然后返回一个boolean值。该接口通常用于判断参数是否满足特定条件,经常用于进行筛滤数据
XxxSupplier 这类接口中通常包含一个getAsXxx()抽象方法,该方法不需要输入参数,该方法会按某种逻辑算法回一个数据。

Lambda表达式可以方便的创建函数式接口的实例

Lambda表达式的本质很简单,就是使用简洁的语法来创建函数式接口的实例,这种语法可以避免创建匿名内部类的烦琐操作。