Java基础加强:lambda 表达式之四大函数式接口
Java8
又称 Java 1.8
版本是自 Java 1.5
版本以来最大的一个版本变动,这一次带来了许多的新特性,首当其冲的莫过于 lambda
表达式,为了配合 lambda
表达式的使用,加入了 函数式
接口。
本文通过几个例子,描述 lambda 表达式结合函数式接口的基本使用方式。
在开始之前,请确定你已经了解并会使用 lambda
表达式
废话不多说,开始!
一、什么是函数式接口
正如其名,函数式接口其实就是表示为函数方式的接口,虽然是函数式,但依然还是一个接口。
这样讲可能有点拗口,通俗点来说,函数式接口就是 只有一个抽象方法的接口。
如:
public interface Com{ |
接口 Com
可被称作一个函数式接口
二、函数式接口的构成
一个函数式接口通常来说必须满足以下两个必要条件
- 首先,它必须是一个 标准的接口定义,不是注解,类,或者枚举。
- 其次,它的接口体内有且仅有一个 抽象方法
接口内的方法默认都是 抽象方法,没有方法体。虽然 Java 1.8 引入了接口默认方法,其中可以有方法体,但其并不能成为抽象方法。所以,在函数式接口中可以存在多个方法,但 抽象方法 必须只有一个。
FunctionalInterface 注解
@FunctionalInterface 是 Java 1.8 引入的注解,是为了配合函数式接口、lambda
表达式而设计的,目的是检查某个接口是否满足函数式接口的定义。
若在接口上标记该注解,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。
需要注意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。总的来说,这个注解可以帮助我们检查接口定义是否符合函数式接口的规范。
泛型
由于函数式接口的特殊性,通常我们都会给其加上泛型。
所以,标准的函数式接口定义为:
//方式一:无默认方法 |
三、如何使用函数式接口
3.1 普通方式
和普通接口一样,函数式接口一样可以通过定义实现类或者匿名内部类的方式进行使用。
定义实现类方式:
public class Goo implements Runn<String>{ |
匿名内部类方式:
Runn<String> runn = new Runn<String>(){ |
但这些并不是我们的重点,关键看 lambda
表达式是如何使用函数式接口的。
3.2 lambda 表达式方式
Runn<String> runn = (a) -> {System.out.println(a)}; |
可以看到,在使用 lambda
表达式之后,整个式子变得非常的简洁。可以说,函数式接口和 lambda
表达式是完全相互融合的。那么,这么简洁的代码是如何执行的呢?又或者说 lambda 表达式的工作又是什么呢?
事实上,lambda 表达式的工作分为 三个部分:
自动实现了等号左边的接口
//Runn<String> runn =
Runn<String> runn = new Goo<String>();将箭头前的参数作为实现的test方法中的参数
//Runn<String> runn = (a) ->
public void test(String a)将箭头后的语句作为实现的 test 方法中的方法体
//Runn<String> runn = (a) -> {System.out.println(a)};
public void test(String a){
System.out.println(a);
}
四、四大函数式接口
Java 1.8 引入函数式接口就是为了解决完全面向对象在某些领域内的痛点,而为了让开发者更高效的使用函数式接口,Java 1.8 还在 java.util.function
包下定义了许多内置的函数式接口,其中最常用的莫过于以下四种:
- Consumer
- Supplier
- Function
- Predicate
4.1 Consumer < T >:消费型接口
消费型接口即指该接口内的唯一抽象方法(void accept(T t)
方法) 只接受输入(有参数) ,没有返回值。只进不出。
/** |
4.2 Supplier < T >:供给型接口
供给型接口即指该接口内的唯一抽象方法 无输入(无参数) ,有返回值。只出不进。
/** |
4.3 Function < T, R > :函数型接口
函数型接口即指该接口内的唯一抽象方法 既有输入(有参数) ,又有返回值。有出有进。
/** |
4.4 Predicate < T >:断言型接口
断言型接口即指该接口内的唯一抽象方法 有输入(有参数) ,且返回值必须为布尔值。有出有进。
/** |
五、其他函数式接口
除了上述 4 种类型的接口外,还有其他的一些接口供我们使用:
BiFunction < T, U, R > 参数类型有2个,为 T,U,返回值为 R,其中方法为
R apply(T t, U u)
。UnaryOperator < T > (Function子接口) 参数为T,对参数为 T 的对象进行一元操作,并返回 T 类型结果,其中方法为
T apply(T t)
。BinaryOperator < T > (BiFunction子接口) 参数为T,对参数为 T 得对象进行二元操作,并返回 T 类型得结果,其中方法为
T apply(T t1, T t2)
。BiConsumer <T, R> 为
void accept(T t, U u)
。ToIntFunction < T >、ToLongFunction < T >、ToDoubleFunction < T > 参数类型为 T,返回值分别为 int,long,double,分别计算 int,long,double 的函数。
IntFunction < R >、LongFunction < R >、DoubleFunction < R > 参数分别为 int,long,double,返回值为 R。
等等…….
以上就是 Java 8 内置的核心函数式接口,其中包括了大部分的方法类型,可以在使用的时候根据不同的使用场景去选择不同的接口使用。
六、参考链接
Java新特性-四大函数式接口