前言
在学习Lambda表达式前,先浇一盆冷水
Lambda不是什么特别神奇的东西,JDK8之前做不到的功能,添加了Lambda表达式还是做不到。
Lambda更多的是一种表达方式上的演进,使得我们用更简洁、精炼、表意的语言来编写代码。
少了匿名类的模式化代码。
函数式接口
所谓函数式接口,就是只有一个抽象方法的接口
所有,也只有函数式接口出现的地方,才能够使用Lambda表达式
为什么呢?
这个也很好理解,因为Lambda本质上是匿名类的一种简单表现形式,其是一段逻辑
的实现
如果出现了多个抽象方法,那么一个Lambda是没办法表示多个逻辑的
接口中可以有默认实现;一个接口,如果有多个默认实现,一个抽象方法,也认为是函数式接口
函数描述符
函数式接口的抽象方法的签名基本上就是Lambda表达式的签名
例如,Runnable接口可以看作一个什么也不接受什么也不返回(void)的函数的
签名,因为它只有一个叫作run的抽象方法,这个方法什么也不接受,什么也不返回(void)
() -> void,代表了参数列表为空,且返回void的函数。这正是Runnable接口所代表的
总之,所谓函数描述符,就是描述了这个函数的请求参数与返回结果类型
@FunctionalInterface
如果是我们自定义的函数式接口,尽量加上这个注解
会执行编译器校验
即:如果我们的接口不符合函数式接口的定义,编译器就会报错
系统提供的函数式接口
Predicate
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
判断对象t
是否符合要求
Consumer
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
处理对象t
,比如可以打印这个对象等等
Function
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
将对象t
转化成对象r
原始类型特化
在Predicate
、Consumer
、Function
翻个函数式接口中,我们能够处理的数据类型都是引用类型,
如果我们要处理的就是int
、double
等基本数据类型该怎么办?
如果我们使用基本数据类型的包装类,也是能够做到的,但是消耗的资源成本过高。
因此,JDK8提供了一组特殊的类,专门处理基本数据类型的函数式接口
方法引用
方法引用可以让我们重复使用方法的定义
方法引用,是特定方法的Lambda表达式的一种快捷写法
它的基本思想是:如果一个Lambda表达式代表的只是”直接调用这个方法“,那最好还是用名称来调用吧
三种方法引用
- 指向静态方法的引用
- 指向任意类型实例方法的引用
- 指向现有对象实例方法的引用
构造函数引用
对于一个有构造函数的类,我们可以用类名::new
的方式来构造对象