Java8中函数接口有很多,大概有几十个吧,具体究竟是多少我也数不清,所以一开始看的时候感觉一脸懵逼,不过其实根本没那么复杂,毕竟不应该也没必要把一个东西设计的很复杂。
几个单词在学习了解之前,希望大家能记住几个单词,掌握这几个单词,什么3,40个官方的函数接口都是小问题了,不信的话接着往下看啦。ok,那这几个单词呢分别是supplier 提供者,consumer 消费者,function 函数,operation 运算符,binary 二元(就是数学里二元一次方程那个二元,代表2个的意思),双重的
四大基础函数接口 函数接口,你可以理解为对一段行为的抽象,简单点说可以在方法就是将一段行为作为参数进行传递,这个行为呢,可以是一段代码,也可以是一个方法,那你可以想象在java8之前要将一段方法作为参数传递只能通过匿名内部类来实现,而且代码很难看,也很长,函数接口就是对匿名内部类的优化。
虽然类库中的基本函数接口特别多,但其实总体可以分成四类,就好像阿拉伯数字是无限多的,但总共就10个基本数字一样,理解了这4个,其他的就都明白了。
function,顾名思义,函数的意思,这里的函数是指数学上的函数哦,你也可以说是严格函数语言中的函数,例如haskell里的,他接受一个参数,返回一个值,永远都是这样,是一个恒定的,状态不可改变的方法。其实想讲函数这个彻底将明白可以再开一篇博客了,所以这里不详细的说了。
上面说到,函数接口是对行为的抽象,因此我方便大家理解,就用java中的方法作例子。
Fcuntion接口是对接受一个T类型参数,返回R类型的结果的方法的抽象,通过调用apply方法执行内容。
public class Operation{ /* 下面这个方法接受一个int类型参数a,返回a+1,符合我上面说的接受一个参数,返回一个值 所以呢这个方法就符合Function接口的定义,那要怎么用呢,继续看例子 */ public static final int addOne(int a){ return a+1; } /* 该方法第二个参数接受一个function类型的行为,然后调用apply,对a执行这段行为 */ public static int oper(int a, Function<Integer,Integer> action){ return action.apply(a); } /* 下面调用这个oper方法,将addOne方法作为参数传递 */ pulic static void main(String[] args){ int x = 1; int y = oper(x,x -> addOne(x));//这里可以换成方法引用的写法 int y = oper(x,Operation::addOne) System.out.printf("x= %d, y = %d", x, y); // 打印结果 x=1, y=2 /* 当然你也可以使用lambda表达式来表示这段行为,只要保证一个参数,一个返回值就能匹配 */ y = oper(x, x -> x + 3 ); // y = 4 y = oper(x, x -> x * 3 ); // y = 3 } }这里的箭头指向的位置就是形参,可以看到第二个箭头的Lambda表达式指向了Funtion接口
Consumer 接口Consumer 接口翻译过来就是消费者,顾名思义,该接口对应的方法类型为接收一个参数,没有返回值,可以通俗的理解成将这个参数\'消费掉了\',一般来说使用Consumer接口往往伴随着一些期望状态的改变或者事件的发生,例如最典型的forEach就是使用的Consumer接口,虽然没有任何的返回值,但是却向控制台输出了语句。
Consumer 使用accept对参数执行行为
Supplier 接口翻译过来就是提供者,和上面的消费者相反,该接口对应的方法类型为不接受参数,但是提供一个返回值,通俗的理解为这种接口是无私的奉献者,不仅不要参数,还返回一个值,使用get()方法获得这个返回值
Supplier<String> getInstance = () -> "HelloWorld!"; System.out.println(getInstance.get()); // 控偶值台输出 HelloWorld Predicate 接口predicate<T,Boolean> 谓语接口,顾名思义,中文中的‘是’与‘不是’是中文语法的谓语,同样的该接口对应的方法为接收一个参数,返回一个Boolean类型值,多用于判断与过滤,当然你可以把他理解成特殊的Funcation<T,R>,但是为了便于区分语义,还是单独的划了一个接口,使用test()方法执行这段行为
public static void main(String[] args) { Predicate<Integer> predOdd = integer -> integer % 2 == 1; System.out.println(predOdd.test(5)); //控制台输出 5 } 其他的接口介绍完正面这四种最基本的接口,剩余的接口就可以很容易的理解了,java8中定义了几十种的函数接口,但是剩下的接口都是上面这几种接口的变种,大多为限制参数类型,数量,下面举几个例子。
类型限制接口