在上一篇文章中我们介绍了JDK1.8的新特性有以下几项。

1.Lambda表达式

2.方法引用

3.函数式接口

4.默认方法

5.Stream

6.Optional类

7.Nashorm javascript引擎

8.新的日期时间API

9.Base64

之前学习了前面两项Lambda表达式,方法引用,这一篇学习函数式接口。

所谓的函数式接口它只能定义一个抽象方法,其他方法可以用default或者static关键对方法进行限定。

下面先来通过实例来验证一下。

自定义一个函数式接口,然后定义一个叫testA的抽象方法,再定义一个叫testB的抽象方法。

此时@FunctionalInterface注解会提示如下错误。(在接口中发现有复数个没有被覆盖的抽象方法)

那我接下来把testB改为非抽象方法试试。

发现改完之后又多了一处错误。我们继续看看新出的错误。

接下来我们把方法加上default关键字

这时候就没有错误信息啦。说明函数式接口中可以除了含有抽象方法外可以有默认的非静态方法。

下面我把default改成static试一试看看可不可以有静态方法。

此时发现也没有问题。那就说明函数式接口中还可以有静态方法。

因为Object类是所有类的父类,所有接口中能被重写的方法都可以在接口中定义。比如

toString,equals方法。

了解完函数式接口,接下来说一下API内置的四大函数式接口。

主要就以下

1. Consumer -- 消费性接口

2. Supplier -- 供给型接口

3. Function -- 函数型接口

4. Predicate -- 断言型接口

下面我们依次来看一下API源代码,以及通过写实例来理解一下每种类型接口使用方法以及特点。

1. Consumer(有传入,没有传出的时候使用)

官方源代码如下,为了起来方便简洁把开头的注释去掉了,只保留了方法的注释。

 1 package java.util.function;
2
3 import java.util.Objects;
4
5 @FunctionalInterface
6 public interface Consumer<T> {
7
8 /**
9 * Performs this operation on the given argument.
10 *
11 * @param t the input argument
12 */
13 void accept(T t);
14
15 /**
16 * Returns a composed {@code Consumer} that performs, in sequence, this
17 * operation followed by the {@code after} operation. If performing either
18 * operation throws an exception, it is relayed to the caller of the
19 * composed operation. If performing this operation throws an exception,
20 * the {@code after} operation will not be performed.
21 *
22 * @param after the operation to perform after this operation
23 * @return a composed {@code Consumer} that performs in sequence this
24 * operation followed by the {@code after} operation
25 * @throws NullPointerException if {@code after} is null
26 */
27 default Consumer<T> andThen(Consumer<? super T> after) {
28 Objects.requireNonNull(after);
29 return (T t) -> { accept(t); after.accept(t); };
30 }
31 }

直接看accept抽象方法,接收一个泛型T类型的t,返回值类型是void,我们把它叫做消费型接口。特点就是有去无回。

下面我们直接看实例

 1 public class InfixFunctionTest {
2 //1.消费型接口
3 @Test
4 public void test1(){
5 //把传入的字符串打印
6 Consumer<String> con = x -> System.out.println(x);//定义函数式的实现
7 con.accept("Hello Consumer!");//接收参数
8 }
9
10 }

执行结果

com.dream.test.JDK8speciality.InfixFunctionTest,test1
Hello Consumer! Process finished with exit code 0

我们只需要在Lambda表达式的参数列表中传入一个x,然后实现是:得到一个无返回类型的打印语句。

2. Supplier(没有传入,有传出的时候使用)

官方源码

 1 package java.util.function;
2
3 /**
4 * Represents a supplier of results.
5 *
6 * <p>There is no requirement that a new or distinct result be returned each
7 * time the supplier is invoked.
8 *
9 * <p>This is a <a href="package-summary.html">functional interface</a>
10 * whose functional method is {@link #get()}.
11 *
12 * @param <T> the type of results supplied by this supplier
13 *
14 * @since 1.8
15 */
16 @FunctionalInterface
17 public interface Supplier<T> {
18
19 /**
20 * Gets a result.
21 *
22 * @return a result
23 */
24 T get();
25 }

get方法没有传入参数,返回一个T,称为供给型接口。特点就是只求回报不求付出。

实例

 1 public class InfixFunctionTest {
2
3 //2.供给型接口
4 @Test
5 public void test2(){
6 Supplier<String> su = () -> new String();
7 String str = su.get();
8 System.out.println("供给型接口的值:" + str);
9 }
10
11 }

执行结果

com.dream.test.JDK8speciality.InfixFunctionTest,test2
供给型接口的值: Process finished with exit code 0

我们在Lambda表达式传入参数用()代表没有参数传入,然后返回一个String类型的对象。

3.Function(有传入参数,传出的时候使用)

官方源码

 1 package java.util.function;
2
3 import java.util.Objects;
4
5 /**
6 * Represents a function that accepts one argument and produces a result.
7 *
8 * <p>This is a <a href="package-summary.html">functional interface</a>
9 * whose functional method is {@link #apply(Object)}.
10 *
11 * @param <T> the type of the input to the function
12 * @param <R> the type of the result of the function
13 *
14 * @since 1.8
15 */
16 @FunctionalInterface
17 public interface Function<T, R> {
18
19 /**
20 * Applies this function to the given argument.
21 *
22 * @param t the function argument
23 * @return the function result
24 */
25 R apply(T t);
26
27 /**
28 * Returns a composed function that first applies the {@code before}
29 * function to its input, and then applies this function to the result.
30 * If evaluation of either function throws an exception, it is relayed to
31 * the caller of the composed function.
32 *
33 * @param <V> the type of input to the {@code before} function, and to the
34 * composed function
35 * @param before the function to apply before this function is applied
36 * @return a composed function that first applies the {@code before}
37 * function and then applies this function
38 * @throws NullPointerException if before is null
39 *
40 * @see #andThen(Function)
41 */
42 default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
43 Objects.requireNonNull(before);
44 return (V v) -> apply(before.apply(v));
45 }
46
47 /**
48 * Returns a composed function that first applies this function to
49 * its input, and then applies the {@code after} function to the result.
50 * If evaluation of either function throws an exception, it is relayed to
51 * the caller of the composed function.
52 *
53 * @param <V> the type of output of the {@code after} function, and of the
54 * composed function
55 * @param after the function to apply after this function is applied
56 * @return a composed function that first applies this function and then
57 * applies the {@code after} function
58 * @throws NullPointerException if after is null
59 *
60 * @see #compose(Function)
61 */
62 default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
63 Objects.requireNonNull(after);
64 return (T t) -> after.apply(apply(t));
65 }
66
67 /**
68 * Returns a function that always returns its input argument.
69 *
70 * @param <T> the type of the input and output objects to the function
71 * @return a function that always returns its input argument
72 */
73 static <T> Function<T, T> identity() {
74 return t -> t;
75 }
76 }

Function接口提供了一个抽象方法,两个默认方法和一个静态方法。这里我只对最常用的抽象方法做出解释。

apply方法接收一个T类型的t,返回一个R类型的值。我们称之为函数型接口。特点就是你来我往。(俗话说的好,来而不往非礼也!哈哈哈!)

实例

 1 public class InfixFunctionTest {
2
3 //3.函数型接口
4 @Test
5 public void test3(){
6 Function<String,Camera> fun = (x) -> new Camera(x);//Function抽象函数的实现。
7 Camera camera = fun.apply("Sony-A7R3");//接收传入的参数
8 System.out.println("cameraName: " + camera.getCameraName() + " price:" + camera.getPrice());
9 }
10
11 }

Camera类

 1 //相机类
2 class Camera{
3 //相机名字
4 private String cameraName;
5 //相机价格
6 private Integer price;
7
8 //无参数构造器
9 public Camera(){
10
11 }
12
13 //有参数构造器
14 public Camera(String cameraName){
15 this.cameraName = cameraName;
16 }
17
18 //有参数构造器
19 public Camera(String cameraName,Integer price){
20 this.cameraName = cameraName;
21 this.price = price;
22 }
23
24 public String getCameraName() {
25 return cameraName;
26 }
27
28 public void setCameraName(String cameraName) {
29 this.cameraName = cameraName;
30 }
31
32 public Integer getPrice() {
33 return price;
34 }
35
36 public void setPrice(Integer price) {
37 this.price = price;
38 }
39 }

执行结果

com.dream.test.JDK8speciality.InfixFunctionTest,test3
cameraName: Sony-A7R3 price:null Process finished with exit code 0

Lam表达式中传入一个参数x,然后x作为构造器的参数,返回一个Camera对象。

4.Predicate(传入一个参数,返回一个布尔类型的结果)

官网源码

 1 package java.util.function;
2
3 import java.util.Objects;
4
5 /**
6 * Represents a predicate (boolean-valued function) of one argument.
7 *
8 * <p>This is a <a href="package-summary.html">functional interface</a>
9 * whose functional method is {@link #test(Object)}.
10 *
11 * @param <T> the type of the input to the predicate
12 *
13 * @since 1.8
14 */
15 @FunctionalInterface
16 public interface Predicate<T> {
17
18 /**
19 * Evaluates this predicate on the given argument.
20 *
21 * @param t the input argument
22 * @return {@code true} if the input argument matches the predicate,
23 * otherwise {@code false}
24 */
25 boolean test(T t);
26
27 /**
28 * Returns a composed predicate that represents a short-circuiting logical
29 * AND of this predicate and another. When evaluating the composed
30 * predicate, if this predicate is {@code false}, then the {@code other}
31 * predicate is not evaluated.
32 *
33 * <p>Any exceptions thrown during evaluation of either predicate are relayed
34 * to the caller; if evaluation of this predicate throws an exception, the
35 * {@code other} predicate will not be evaluated.
36 *
37 * @param other a predicate that will be logically-ANDed with this
38 * predicate
39 * @return a composed predicate that represents the short-circuiting logical
40 * AND of this predicate and the {@code other} predicate
41 * @throws NullPointerException if other is null
42 */
43 default Predicate<T> and(Predicate<? super T> other) {
44 Objects.requireNonNull(other);
45 return (t) -> test(t) && other.test(t);
46 }
47
48 /**
49 * Returns a predicate that represents the logical negation of this
50 * predicate.
51 *
52 * @return a predicate that represents the logical negation of this
53 * predicate
54 */
55 default Predicate<T> negate() {
56 return (t) -> !test(t);
57 }
58
59 /**
60 * Returns a composed predicate that represents a short-circuiting logical
61 * OR of this predicate and another. When evaluating the composed
62 * predicate, if this predicate is {@code true}, then the {@code other}
63 * predicate is not evaluated.
64 *
65 * <p>Any exceptions thrown during evaluation of either predicate are relayed
66 * to the caller; if evaluation of this predicate throws an exception, the
67 * {@code other} predicate will not be evaluated.
68 *
69 * @param other a predicate that will be logically-ORed with this
70 * predicate
71 * @return a composed predicate that represents the short-circuiting logical
72 * OR of this predicate and the {@code other} predicate
73 * @throws NullPointerException if other is null
74 */
75 default Predicate<T> or(Predicate<? super T> other) {
76 Objects.requireNonNull(other);
77 return (t) -> test(t) || other.test(t);
78 }
79
80 /**
81 * Returns a predicate that tests if two arguments are equal according
82 * to {@link Objects#equals(Object, Object)}.
83 *
84 * @param <T> the type of arguments to the predicate
85 * @param targetRef the object reference with which to compare for equality,
86 * which may be {@code null}
87 * @return a predicate that tests if two arguments are equal according
88 * to {@link Objects#equals(Object, Object)}
89 */
90 static <T> Predicate<T> isEqual(Object targetRef) {
91 return (null == targetRef)
92 ? Objects::isNull
93 : object -> targetRef.equals(object);
94 }
95 }

Predicate接口提供了一个抽象方法,三个默认方法和一个静态方法。这里是对抽象方法进行举例说明。

由于返回一个布尔类型的值,我们称之为断言型。特点就是发出请求,等待指示(做还是不做,哈哈)。

 1 public class InfixFunctionTest {
2
3 //4.断言式接口
4 @Test
5 public void test4(){
6 Predicate<String> pre = x -> x == null;
7 Boolean b =pre.test(null);
8 System.out.println("断言式测试结果:" + b);
9 }
10
11 }

执行结果

com.dream.test.JDK8speciality.InfixFunctionTest,test4
断言式测试结果:true Process finished with exit code 0

Lambda表达式传入一个参数x,判断x是不是null。

以上实例中都省略了头部的打包和导入包信息,包信息如下。

1 package com.dream.test.JDK8speciality;
2
3 import org.junit.Test;
4
5 import java.util.function.Consumer;
6 import java.util.function.Function;
7 import java.util.function.Predicate;
8 import java.util.function.Supplier;

java.util.function包下除了上面这几个基本函数式接口外,还有好多。其他的都是这几个基本的衍生。这几个搞懂了,其他的就都不难理解了。有兴趣的可以自己进行研究。

以上就是对函数式的学习。如果各位大神发现有不对或者不好的地方,欢迎指正。非常感谢!

上一篇文章

JDK1.8新特性之(二)--方法引用

JDK1.8新特性之(三)--函数式接口的更多相关文章

  1. Java JDK1.8新特性之四大函数式接口

    JDK 1.8的一些新特性 四大核心函数式接口(Consumer.Predicate.Supplier.Function),结合lambda表达式 import java.util.ArrayList ...

  2. java8新特性学习:函数式接口

    本文概要 什么是函数式接口? 如何定义函数式接口? 常用的函数式接口 函数式接口语法注意事项 总结 1. 什么是函数式接口? 函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:SAM类型的接口 ...

  3. 01 语言基础+高级:1-10 JDK8新特性_day12【函数式接口】

    day12[函数式接口] 主要内容自定义函数式接口函数式编程常用函数式接口 教学目标能够使用@FunctionalInterface注解能够自定义无参无返回函数式接口能够自定义有参有返回函数式接口能够 ...

  4. JAVA 8 主要新特性 ----------------(四)Lambda函数式接口

    一.什么是函数式接口 只包含一个抽象方法的接口,称为函数式接口.  你可以通过 Lambda 表达式来创建该接口的对象.(若 Lambda 表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法 ...

  5. java8新特性 - 什么是函数式接口 @FunctionalInterface?

    什么是函数式接口 @FunctionalInterface 源码定义 /** * An informative annotation type used to indicate that an int ...

  6. Java8新特性探索之函数式接口

    一.为什么引入函数式接口 作为Java函数式编程爱好者,我们都知道方法引用和 Lambda 表达式都必须被赋值,同时赋值需要类型信息才能使编译器保证类型的正确性. 我们先看一个Lambda代码示例: ...

  7. JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用

    jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default   Lambda表达式     L ...

  8. JDK1.8新特性——Collector接口和Collectors工具类

    JDK1.8新特性——Collector接口和Collectors工具类 摘要:本文主要学习了在Java1.8中新增的Collector接口和Collectors工具类,以及使用它们在处理集合时的改进 ...

  9. JDK1.8新特性(一): 接口的默认方法default

    前言 今天在学习mysql分区优化时,发现一个博客专家大神,对其发布的文章简单学习一下: 一:简介 我们通常所说的接口的作用是用于定义一套标准.约束.规范等,接口中的方法只声明方法的签名,不提供相应的 ...

随机推荐

  1. k8s-1.15.0集群部署+dashboard

    环境:外网环境硬件master-centos7.4  2核4G node1-centos7.4     2核4Gnode2-centos7.4     2核4G软件:三台服务器 :docker-19. ...

  2. laravel中elastisearch安装和测试运行是否成功(注意是windows下的操作)

    1.去elasticsearch官网下载,如果太慢可以在我上一个随笔看下载地址 2.下载完解压缩,在cmd中找到到elasticsearch的bin目录下执行.\elasticsearch.bat - ...

  3. 【HttpRunner v3.x】笔记—6. 测试用例-teststeps-RunRequest

    之前我们了解了config里的各项参数,今天来了解另一个重要部分--teststeps,在这之前,先看看测试用例的分层模型. 一.测试用例分层模型 一个testcase里(就是一个pytest格式的P ...

  4. JVM内存区域以及各区域的内存溢出异常,内存分代策略,垃圾收集算法,各种垃圾收集器

    本文整理自周志明老师的<深入理解Java虚拟机-JVM高级特性与最佳实践>第3版的第二章和第三章. 加上了一些网上拼拼凑凑的图片,个人认为很多博客复制来复制去,最后的东西都看不懂,所以从书 ...

  5. [BUUOJ记录] [CISCN 2019 初赛]Love Math & [NESTCTF 2019]Love Math 2

    主要考察利用已有函数构造危险函数绕过,实现RCE. 进入题目给出源码: <?php error_reporting(0); //听说你很喜欢数学,不知道你是否爱它胜过爱flag if(!isse ...

  6. js error 错误处理

    (new) Error([message[, fileName[,lineNumber]]]) 单独定义Error()错误,函数继续进行 当像函数一样使用 Error 时 -- 如果没有 new,它将 ...

  7. 一文读懂神经网络训练中的Batch Size,Epoch,Iteration

    一文读懂神经网络训练中的Batch Size,Epoch,Iteration 作为在各种神经网络训练时都无法避免的几个名词,本文将全面解析他们的含义和关系. 1. Batch Size 释义:批大小, ...

  8. odoo10甘特图gantt view

    odoo10中的gantt图示例 1.Gantt属性说明 甘特图视图的根元素是<gantt />,它没有子节点但可以采用以下属性: date_start (required) 提供每条记录 ...

  9. appium多线程自动化

    基于上篇讲述的appium自动启动停止.测试服务.对controller文件进行相应的修改 1.首先对start_server函数,应采用多线程模式启动多个server,如下 其中启动的每个线程函数s ...

  10. graph attention network(ICLR2018)官方代码详解(tensorflow)-稀疏矩阵版

    论文地址:https://arxiv.org/abs/1710.10903 代码地址: https://github.com/Diego999/pyGAT 之前非稀疏矩阵版的解读:https://ww ...