函数式接口
本文章抄录于noteless
学习使用,无其他想法
函数式接口详细定义

一种用于表示一个接口是Java语言规范定义的函数式接口的注解类型.
关键概念
从文件注释中我们可以看到函数式接口的关键概念
函数式接口只有一个抽象方法
由于default方法有一个实现,所以他们不是抽象的.
如果一个接口定义了一个抽象方法,而他恰好覆盖了Object的public方法,仍旧不算做接口的抽象方法, 因为它终将会在某处得到一个实现.(如果不是public的那么计数)
也即是只有一个抽象方法默认不算,Object的public也不算
函数式接口的实例可以通过 lambda表达式 方法引用 或者构造方法引用进行表示
类型必须是接口,而不能是其他的比如class 而且需要符合函数式接口的定义要求 否则使用注解时编译器报错
不管他们是否有使用注解FunctionalInterface 进行注解, 编译器将会把任何满足函数式接口定义的接口当做一个函数式接口 也就是说不加也行,但是显然不加的话,就没有限制约束,后续可能增加了其他方法导致出错
常用函数式接口
| 四大基础接口 | java.util.function 包 |
|---|---|
| 接口 | 抽象方法 |
| Predicate |
boolean test(T t); |
| Consumer |
void accept(T t); |
| Function<T, R> 函数型 | R apply(T t); |
| Supplier |
T get(); |
java.util.function.Predicate<T>
断言 也就是条件测试器 接收条件,进行测试
接口定义了一个名叫test的抽象方法,它接受泛型T对象,并返回一个boolean。
test (条件测试) , and-or- negate(与或非) 方法

java.util.function.Consumer<T>
消费者 消费数据 接收参数,返回void 数据被消费了
定义了一个名叫accept的抽象方法,它接受泛型T的对象,没有返回(void)
你如果需要访问类型T的对象,并对其执行某些操作,就可以使用这个接口

java.util.function.Function<T, R>
函数 有输入有输出 数据转换功能
接口定义了一个叫作apply的方法,它接受一个泛型T的对象,并返回一个泛型R的对象。

java.util.function.Supplier<T>
提供者 不需要输入,产出T 提供数据
无参构造方法 提供T类型对象

接口中的compose, andThen, and, or, negate 用来组合函数接口而得到更强大的函数接口
四大接口为基础接口,其他的函数接口都是通过这四个扩展而来的
此处的扩展是指概念的展开 不是平常说的继承或者实现,当然实现上可能是通过继承比如UnaryOperator
扩展方式:
参数个数上扩展
比如接收双参数的,有 Bi 前缀, 比如 BiConsumer<T,U>, BiFunction<T,U,R> ;
特殊常用的变形
比如 BinaryOperator , 是同类型的双参数 BiFunction<T,T,T> ,二元操作符 ; UnaryOperator 是 Function<T,T> 一元操作符。
类型上扩展
比如接收原子类型参数的,比如 [Int|Double|Long] [Function|Consumer|Supplier|Predicate]
为什么要有基本类型扩展
只有对象类型才能作为泛型参数,对于基本类型就涉及到装箱拆箱的操作,虽然是自动的
但是这不可避免给内存带来了额外的开销,装箱和拆箱都会带来开销
所以为了减小这些性能开销 对基本类型进行类型扩展
Stream 类的某些方法对基本类型和装箱类型做了区分
Java 8中,仅对 整型、长整型和双浮点型做了特殊处理 因为它们在数值计算中用得最多
对基本类型做特殊处理的方法在命名上有明确的规范
如果参数是基本类型,则不加前缀只需类型名即可
如果方法返回类型为基本类型,则在基本类型前再加上一个 To
总结一句话:
加了类型前缀[Int|Double|Long] 表示参数是基本类型, 如果在此基础上又加上了To 表示返回类型是基本类型
如有可能,应尽可能多地使用对基本类型做过特殊处理的方法,进而改善性能

浙公网安备 33010602011771号