在上一节中我们谈到Java8对原有的接口进行了增强,除此之外,Java8中还提出了一个新名词——函数式接口1(Functional Interface),用来特指某类型的接口。这类接口中定义了唯一的抽象方法,在早期这类接口被叫做SAM类型接口(single abstract interface),比如我们常见的Runnable接口。需要注意的是接口的默认方法和静态方法并不影响一个接口成为函数式接口。
除了早期存在的Runnable,Comparator等函数式接口之外,jdk8中又增加了java.util.function包,其中提供了常用的函数式接口,比如:
- Predicate
- Function
- Consumer
- Supplier
另外,java 8中也提供了@FunctionalInterface注解用于标记一个接口是函数式接口,该注解被用来显式告知用户这是一个函数式接口,java并不强制要求要为函数式接口标记此注解。实际上一个接口是否是函数式接口由虚拟机来判断。这里我们自行定义一个函数式接口:
public class FunctionalInterfaceTest {
public static void main(String[] args) {
Calculate calculate=new Calculate() {
@Override
public void applay(int i) {
System.out.println(i);
}
};
calculate.applay(8);
}
@FunctionalInterface
interface Calculate {
void applay(int i);
}
}
看完示例代码,你可能觉得它和普通接口的使用也没有什么不同,那为什么java团队会提出函数式接口这个概念呢?其根本原因在于:函数式接口完全是为了Java 中Lambda的实现而定义的。在lambda的实现过程中,java开发团队选择利用SAM接口作为Lambda表达式的目标类型,凡是在函数式接口出现的地方,都可以接受一个Lambda表达式作为函数式接口的实现。(Lambda表达式不能脱离上下文单独存在,它必须要有一个明确的目标类型,该目标类型也就是函数式接口)
到现在我们彻底明白函数式接口完全是为实现Lambda而提出的。那现在我们利用Lambda表达式来改写上例:
public class FunctionalInterfaceTest {
public static void main(String[] args) {
Calculate calculate = param ->System.out.println(param);
calculate.applay(8);
}
@FunctionalInterface
interface Calculate {
void applay(int i);
}
}
到现在为止,我们已经认识了函数式接口,它将帮助我们理解Lambda的使用场景。
- 也被叫做功能性接口,两者是同一回事。 ↩