函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
一、自定义
在自定义接口前,我们要先认识一下@FunctionalInterface注解:
- @FunctionalInterface注解只能标注一个接口,不能标注
类
,方法,枚举,属性等。 - 如果接口被标注了
@FunctionalInterface
,这个类就必须符合函数式接口的规范 - 即使一个接口没有标注
@FunctionalInterface
,如果这个接口满足函数式接口规则,依旧被当作函数式接口。
根据最上文的定义,我们能非常直白的理解什么是函数式接口的规则。(1)有且只有一个抽象方法。(2)可以有很多非抽象的方法,当然根据jdk1.8的新特性,接口中的非抽象方法需要用default修饰。下面我们自定义一个函数式接口:
@FunctionalInterface
public interface Square {
int square(int x);
defalut int compute(int x){
System.out.println(square(x));
}
}
public class FunctionalInterfaceTest{
public static void test(int x, Square square){
square.compute(x);
}
public static void main(String[] args){
int a=10;
Square square = (x) -> x * x;
test(a,square);
// 或者直接写成
int a=10;
test(a,(x) -> x * x)
}
}
上面是一个非常简单的例子,自定义了一个接口Square,抽象函数square求平方,compute打印计算结果。
二、官方接口
java.util.function包中为我们提供了43种函数式接口,调用起来非常方便。因此,很多情况下,我们不需要自己去定义函数式接口。
name | type | description |
Consumer | Consumer< T > | 接收T对象,不返回值 |
Predicate | Predicate< T > | 接收T对象并返回boolean |
Function | Function< T, R > | 接收T对象,返回R对象 |
Supplier | Supplier< T > | 提供T对象(例如工厂),不接收值 |
UnaryOperator | UnaryOperator | 接收T对象,返回T对象 |
BinaryOperator | BinaryOperator | 接收两个T对象,返回T对象 |
上表为java.util.function中的部分接口,我们采用Function< T, R >模板举个例子:
public class FunctionTest{
public static Integer compute(Integer x,Function<Integer,Integer> function){
Integer re = function.apply(x)
System.out.println(re);
return re;
}
public static void main(String[] args){
int x = 10;
// 平方
compute(x,y->y*y);
// 加倍
compute(x,y->y+y);
}
}
三、什么时候需要自定义函数式接口(引用于Effective java 第44条)
1、只要标准的函数接口能够满足需求,通常应该优先考虑,而不是专门再构建一个新的函数接口 。 这样会使 API 更加容易学习,通过减少它的概念内容,显著提升互操作性优势,因为许多标准的函数接口都提供了有用的默认方法 。
2、如果你所需要的函数接口与 Comparator 一样具有一项或者多项以下特征, 则必须认真考虑自己编写专用的函数接口,而不是使用标准的函数接口 :
(1) 通用,并且将受益于描述性的名称 。
(2) 具有与其关联的严格的契约 。
(3) 将受益于定制的缺省方法 。
以 Comparator< T>为例 , 它与 TointBiFunction<T , T>接口在结构上一致,虽然前者被添加到类库中时,后一个接口已经存在,但如果用后者就错了 。 Comparator 之所以需要有自己的接口,有三个原因 。 首先,每当在 API 中使用时,其名称提供了良好的文档信息,并且被大量使用 。 其次, Comparator 接口对于如何构成一个有效的实例,有着严格的条件限制,这构成了它的总则( general contract ) 。 实现该接口相当于承诺遵守其契约 。 第三 ,这个接口配置了大量很好用的缺省方法,可以对比较器进行转换和合并 。