JDK1.8新特性之(三)--函数式接口
在上一篇文章中我们介绍了JDK1.8的新特性有以下几项。
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新特性之(三)--函数式接口的更多相关文章
- Java JDK1.8新特性之四大函数式接口
JDK 1.8的一些新特性 四大核心函数式接口(Consumer.Predicate.Supplier.Function),结合lambda表达式 import java.util.ArrayList ...
- java8新特性学习:函数式接口
本文概要 什么是函数式接口? 如何定义函数式接口? 常用的函数式接口 函数式接口语法注意事项 总结 1. 什么是函数式接口? 函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:SAM类型的接口 ...
- 01 语言基础+高级:1-10 JDK8新特性_day12【函数式接口】
day12[函数式接口] 主要内容自定义函数式接口函数式编程常用函数式接口 教学目标能够使用@FunctionalInterface注解能够自定义无参无返回函数式接口能够自定义有参有返回函数式接口能够 ...
- JAVA 8 主要新特性 ----------------(四)Lambda函数式接口
一.什么是函数式接口 只包含一个抽象方法的接口,称为函数式接口. 你可以通过 Lambda 表达式来创建该接口的对象.(若 Lambda 表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法 ...
- java8新特性 - 什么是函数式接口 @FunctionalInterface?
什么是函数式接口 @FunctionalInterface 源码定义 /** * An informative annotation type used to indicate that an int ...
- Java8新特性探索之函数式接口
一.为什么引入函数式接口 作为Java函数式编程爱好者,我们都知道方法引用和 Lambda 表达式都必须被赋值,同时赋值需要类型信息才能使编译器保证类型的正确性. 我们先看一个Lambda代码示例: ...
- JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用
jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default Lambda表达式 L ...
- JDK1.8新特性——Collector接口和Collectors工具类
JDK1.8新特性——Collector接口和Collectors工具类 摘要:本文主要学习了在Java1.8中新增的Collector接口和Collectors工具类,以及使用它们在处理集合时的改进 ...
- JDK1.8新特性(一): 接口的默认方法default
前言 今天在学习mysql分区优化时,发现一个博客专家大神,对其发布的文章简单学习一下: 一:简介 我们通常所说的接口的作用是用于定义一套标准.约束.规范等,接口中的方法只声明方法的签名,不提供相应的 ...
随机推荐
- 用maven整合SSM中jsp运行报404和500问题解决方案
如果代码检查没有错误,建议更改maven版本,可以改为maven-3.6.1 网址:https://archive.apache.org/dist/maven/maven-3/ 选择3.6.1 再点击 ...
- day43:CSS样式相关
目录 1.高度和宽度 2.字体相关 3.字体对齐 4.颜色设置 5.背景 6.边框 7.盒子模型 8.display属性 9.伪元素选择器 10.伪类选择器 11.浮动 12.文字装饰 13.相对定位 ...
- Spring Security如何优雅的增加OAuth2协议授权模式
一.什么是OAuth2协议? OAuth 2.0 是一个关于授权的开放的网络协议,是目前最流行的授权机制. 数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据.系统从而产生一个短期的进入令 ...
- Android Studio出现:Your project path contains non-ASCII 错误代码解决方法
导入Project的出现: Error:(1, 0) Your project path contains non-ASCII characters. This will most likely ca ...
- oeasy 教您玩转linux010101查看内核uname
linux([?l?n?ks]) 是什么????? 咱们这次讲点什么呢?这次咱们讲讲这个 linux([?l?n?ks]),什么是 linux([?l?n?ks])呢?这linux([?l?n?ks] ...
- Unity3D中可重载虚函数的总结
重载虚函数:Unity3D中所有控制脚本的基类MonoBehaviour有一些虚函数用于绘制中事件的回调,也可以直接理解为事件函数,例如大家都很清楚的Start,Update等函数,以下做个总结. A ...
- Linq 下的扩展方法太少了,您期待的 MoreLinq 来啦
一:背景 1. 讲故事 前几天看同事在用 linq 给内存中的两个 model 做左连接,用过的朋友都知道,你一定少不了一个叫做 DefaultIfEmpty 函数,这玩意吧,本来很流畅的 from. ...
- Spark应用开发-关联分析
在机器学习中,常用的主题有分类,回归,聚类和关联分析.而关联分析,在实际中的应用场景,有部分是用于商品零售的分析.在Spark中有相应的案例 在关联分析中,有一些概念要熟悉. 频繁项集,关联规则,支持 ...
- Oracle中select子句取值先于order by子句执行而导致rownum伪列未按预期取值导致的问题
有这么一张表: create table hytb( id number(4,0) not null primary key, padid nvarchar2(20) not null, inputd ...
- String源码浅析
如果问你,开发过程中用的最多的类是哪个?你可能回答是HashMap,一个原因就是HashMap的使用量的确很多,还有就是HashMap的内容在面试中经常被问起. 但是在开发过程中使用最多的类其实并不是 ...