掌握内容
- 函数式接口概念和意义
- 认识JDK内置函数式接口
- 函数式接口配合Lambda实现
- 自定义函数式接口
- @FunctionalInterface注解作用
函数式接口
函数式接口就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,是Lambda表达式的实现前提,可以使用@FunctionalInterface注解修饰
函数式接口意义
Java一直倡导面向对象,随着Python、Scala等语言的兴起和新技术的挑战,Java必须调整来支持更加广泛的技术要求,所以Java不单单OOP【面向对象编程】同样支持OOF【面向函数编程】。
以往需要通过匿名内部类实现,现在都可以通过Lambda实现,其实Lambda表达式可以看做是一个函数式接口的实例。
JDK内置函数式接口
注:不需要掌握,不需要掌握!我看网上很多资料都只写了四个内置接口,比较局限,这里对JDK内置接口做一个全面的说明,只需要知道有这么多内置接口,并不是只有四个就可以了。
JDK8新增函数式接口:
JDK8新推出的函数式接口在java.util.function包下
作用如下:
函数式接口 | 参数类型 | 返回类型 | 用途 |
Consumer 消费型接口 | T | void | 对类型为T的对象应用操作,包含方法:void accept(T t) |
Supplier 供给型接口 | 无 | T | 返回类型为T的对象,包含方法:T get() |
Function | T | R | 对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(T t) |
Predicate断定型接口 | T | boolean | 确定类型为T的对象是否满足某约束,并返回boolean 值。包含方法:boolean test(T t) |
BiFunction | T, U | R | 对类型为T,U参数应用操作,返回R类型的结果。包含方法为:Rapply(T t,U u) |
UnaryOperator(Function子接口) | T | T | 对类型为T的对象进行一元运算,并返回T类型的结果。包含方法为:Tapply(T t); |
BinaryOperator(BiFunction子接口) | T,T | T | 对类型为T的对象进行二元运算,并返回T类型的结果。包含方法为:Tapply(T t1,T t2); |
BiConsumer | T,U | void | 对类型为T,U参数应用操作。包含方法为:voidaccept(Tt,Uu) |
BiPredicate | T,U | boolean | 包含方法为:booleantest(Tt,Uu) |
ToIntFunction | T | int | 计算int值的函数 |
ToLongFunction | T | long | 计算long值的函数 |
ToDoubleFunction | T | double | 计算double值的函数 |
IntFunction | int | R | 参数为int类型的函数 |
LongFunction | long | R | 参数为long类型的函数 |
DoubleFunction | double | R | 参数为double类型的函数 |
JDK8之前的函数式接口:
JDK8之前也存在函数式接口,在JDK8升级之后这些接口头部都加上了@FunctionalInterface修饰,如下:
- java.lang.Runnable【熟悉吧,创建线程】
- java.util.concurrent.Callable【创建线程】
- java.security.PrivilegedAction【执行计算】
- java.util.Comparator【Lambda一篇说过的 比较器】
- java.io.FileFilter【文件过滤器】
- java.nio.file.PathMatcher【路径匹配】
- java.lang.reflect.InvocationHandler【动态代理】
- java.beans.PropertyChangeListener【属性变化监听器】
- java.awt.event.ActionListener【事件监听器】
- javax.swing.event.ChangeListener【change事件监听】
函数式接口使用
在上篇中我们已经使用过Runnable、Consumer、Supplier、Comparator等接口,这里我们再使用Function和Predicate接口,其他接口如果用到了可以照葫芦画瓢即可!
Function接口
接口定义如下:
小贴士:接口中有且仅有一个抽象方法的接口就是一个函数式接口,和默认实现以及静态方法无关。
接口特点:有一个输入参数和一个输出参数,也就是一进一出,如果你有需求是传入一个参数并返回一个参数的需求可以使用该接口实现。
需求:
实现一个字符串转换功能,将输入的英文字符都转换为大写返回。
分析:
输入和输出数据都是字符串所有泛型类型均为String。
调用 apply方法进行计算之后接收返回值。
代码实现:
Predicate接口
接口定义:
该接口也存在默认实现和静态方法,但是只有一个抽象方法,所以也是一个函数式接口。
接口特点:该接口根据传入数据通过计算之后返回true或者false,如果你想要做单个参数的判断可以使用该接口。
小贴士:Java中有两个Predicate类,不要导错包,认准java.util.function包,当然自定义的类也不要起这个名字,【有许多初学者喜欢起同名的类】。
需求:判断输入的数据是否大于0。
分析:
- 泛型定义为Integer类型。
- 通过判断返回结果即可。
代码实现:
小贴士:这些默认方法的接口,使用时不要调用错方法就行!
自定义函数式接口
分析:
函数式接口就是有且仅有一个抽象方法,默认实现和静态方法不影响它是一个函数式接口【JDK8支持接口有默认方法和静态方法】。
接口,定义抽象即可,所以我这里都使用泛型,可以根据自己的需求定义,如果需求要限制类型也可以直接定义成具体的类型。
接口定义:
接口使用:
Lambda表达式就是香。
包含默认实现的函数式接口:
包含默认方法和静态方法并不影响它是一个函数式接口。
有多个抽象方法:
有两个以上抽象方法就不再是一个函数式接口,所以@FunctionalInterface注解报错,该注解可以用来检验接口是否为一个函数式接口。
@FunctionalInterface注解
Java 8中专门为函数式接口引入了一个新的注解:@FunctionalInterface 。该注解放在接口上,表示此接口是一个函数式接口。并且提示编译器去检查接口是否仅包含一个抽象方法,即,是否符合函数式编程的定义。
小贴士:如果自定义一个符合规范的函数式接口,也可以不加@FunctionalInterface注解,此注解只是起到一个提示编译器进行规范检查的作用
总结
- 技术升级都是系统性的,仅升级修改某一部分通常是修复BUG。
- 函数式接口是Lambda的前提,JDK8之前通过匿名内部类实现,Lambda让编码变的简洁。
- 函数式接口中有且仅有一个抽象方法。
- 函数式接口可以使用@FunctionalInterface检验,也可以不使用该注解。
- JDK内置了许多函数式接口,可以按需使用,我们也可以自定义函数式接口。
- 在阅读部分框架源码时一定要认识Lambda表达式和函数式接口哦。
文章出自:添甄,如有转载本文请联系【添甄】今日头条号。