Java 双冒号 参数 jdk8双冒号_函数式接口


前言

从毕业到现在正好三年,高难度的项目做了不少,但是基础这个东西一段时间不接触就会忘得一干二净。话不多说,开始今天的学习!

1. Consumer接口

接触过“消费者”,“生产者”模式的同学,肯定对这个单词不陌生,在java8函数式编程和lambda表达式加入之后,这个接口直接深入的影响了之前的集合,JAVA8中Iterable的源代码如下:


package


顺便提到的是 default这个接口的默认方法是一起在JAVA8中加入的。

相信大家在处理集合时或多或少都用到了“forEach”这个遍历方法,不得不说这个方法真的是很好用。


package


jdk8中使用了::的用法。就是把方法当做参数传到stream内部,使stream的每个元素都传入到该方法里面执行一下,双冒号运算就是Java中的[方法引用],[方法引用]的格式是:

类名::方法名

注意此处没有()

一般的lambda表达式就是 -> 符号,跟c++中的调用类中的参数一样。

这样的代码看起来就很整齐,而且在可读性方面也很不错。但是我们今天的主角是Consumer,接下来我换一种写法:


package


唉?这不是我们非常熟悉的匿名内部类吗~

没错,lambda表达式将匿名内部类的创建简化成了一个符号。接下来就该隆重的请上Consumer的源码了:


package


首先这个接口呢有一个@FunctionalInterface注解,Java 8为函数式接口引入了一个新注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。

所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法

这种类型的接口也称为SAM接口,即Single Abstract Method interfaces。

当我们用lambda表达式来时限Consumer接口时,其实就是在实现接口中的这个唯一抽象方法,由于Consumer设计出来是处理数据,并且是不带返回值的,所以在处理打印日志,数据库操作的时候会比较常用到。所以方法里面还有一个andThen方法,顾名思义,就是可以顺序来执行多个Consumer,如下:


package


我做了一个打印X3的效果,结果如下:

0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 7 8 8 8 9 9 9 10 10 10

所以Consumer作为一个不返回结果的流处理接口,这方面还是很给力的。

作为函数式编程的第一个接口,特点就是“有入参,无出参”。

下一章我们继续学习Predicate接口