什么是函数式接口

先来看看传统的创建线程是怎么写的

Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1");
}
});
t1.start();

再来看看使用了函数式接口是怎么写的

Thread t2 = new Thread(() -> System.out.println("t2"));
t2.start();

Runnable接口直接可以使用Lambda表达式来编写,这是因为Runnable接口是一个函数式接口,来看看Runnable的源码。

@FunctionalInterface
public interface Runnable { public abstract void run(); }

发现该接口加上了函数式接口的定义注解:@FunctionalInterface,表明该接口是一个函数式接口。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface { }

在JDK8中,除了Runnbale接口,还有像Comparator、Callable等接口都加上了该注解定义为函数式接口。

内置函数式接口

JDK8提供了几个内置的函数式接口,用在了许多API的地方,都可以拿来用,可以满足大部分应用。

//Consumer<T> - T作为输入,执行某种动作但没有返回值
Consumer<String> con = (x) -> {
System.out.println(x);
};
con.accept("hello world"); //Supplier<T> - 没有任何输入,返回T
Supplier<String> supp = () -> {
return "Supplier";
};
System.out.println(supp.get()); //Predicate<T> -T作为输入,返回的boolean值作为输出
Predicate<String> pre = (x) -> {
System.out.print(x);
return x.startsWith("op");
};
System.out.println(": " + pre.test("op, hello World")); // Function<T, R> -T作为输入,返回的R作为输出
Function<String, String> function = (x) -> {
System.out.print(x + ": ");
return "Function";
};
System.out.println(function.apply("hello world")); //BinaryOperator<T> -两个T作为输入,返回一个T作为输出,对于“reduce”操作很有用
BinaryOperator<String> bina = (x, y) -> {
System.out.print(x + " " + y);
return "BinaryOperator";
};
System.out.println(" " + bina.apply("hello ", "world"));

自定义函数式接口

1、自定义一个函数式接口

@FunctionalInterface
public interface CalcInterface<N, V> {
V operation(N n1, N n2);
}

这里只有一个抽象方法,@FunctionalInterface注解可以不用写,至于为什么可以往下看。

2、新建一个引用函数式接口的类

public static class NumberOperation<N extends Number, V extends Number> {

    private N n1;
private N n2; public NumberOperation(N n1, N n2) {
this.n1 = n1;
this.n2 = n2;
} public V calc(CalcInterface<N, V> ci) {
V v = ci.operation(n1, n2);
return v;
} }

3、测试函数式接口

private static void testOperationFnInterface() {
NumberOperation<Integer, Integer> np = new NumberOperation(13, 10); CalcInterface<Integer, Integer> addOper1 = (n1, n2) -> {
return n1 + n2;
};
CalcInterface<Integer, Integer> multiOper1 = (n1, n2) -> {
return n1 * n2;
};
System.out.println(np.calc1(addOper1));
System.out.println(np.calc1(multiOper1)); // 上面的可以简写为
System.out.println(np.calc1((n1, n2) -> n1 + n2));
System.out.println(np.calc1((n1, n2) -> n1 * n2));
}

最后输出:

23
130
23
130

函数式接口规范

1、@FunctionalInterface标识为一个函数式接口只能用在只有一个抽象方法的接口上。

2、接口中的静态方法、默认方法、覆盖了Object类的方法都不算抽象方法。

3、@FunctionalInterface注解不是必须的,如果该接口只有一个抽象方法可以不写,它默认就符合函数式接口,但建议都写上该注解,编译器会检查该接口是否符合函数式接口的规范。

举例说明

正确的函数式接口。

@FunctionalInterface
public interface CalcInterface<N, V> {
V operation(N n1, N n2);
}

加了几个符合函数式的方法也没事,编译器也不会报错。

@FunctionalInterface
public interface CalcInterface<N, V> { V operation(N n1, N n2); public boolean equals(Object object); public default void defaultMethod() { } public static void staticMethod() { }
}

这个没用@FunctionalInterface函数式接口,有两个抽象方法,不能用于Lambda表达式。

public interface CalcInterface<N, V> {
V operation(N n1, N n2);
V operation2(N n1, N n2);
}

这个有两个抽象方法的用@FunctionalInterface注解的函数式接口编译会报错。

@FunctionalInterface
public interface CalcInterface<N, V> {
V operation(N n1, N n2);
V operation2(N n1, N n2);
}

这个没有一个抽象方法,编译报错。

public interface CalcInterface<N, V> {
}

推荐阅读

干货:免费领取2TB架构师四阶段视频教程

面经:史上最全Java多线程面试题及答案

工具:推荐一款在线创作流程图、思维导图软件

分享Java干货,高并发编程,热门技术教程,微服务及分布式技术,架构设计,区块链技术,人工智能,大数据,Java面试题,以及前沿热门资讯等。

JDK8新特性之函数式接口的更多相关文章

  1. JDK8新特性:函数式接口

    一,定义 函数式接口,英文为Functional Interface.首先它是一个接口,那么它与其它接口有什么不同呢?不同点就是在这个接口中只允许有一个抽象方法. 这里的只允许一个抽象方法不包括以下几 ...

  2. JDK8新特性:函数式接口@FunctionalInterface的使用说明

    我们常用的一些接口Callable.Runnable.Comparator等在JDK8中都添加了@FunctionalInterface注解. 通过JDK8源码javadoc,可以知道这个注解有以下特 ...

  3. 乐字节-Java8新特性之函数式接口

    上一篇小乐带大家学过 Java8新特性-Lambda表达式,那什么时候可以使用Lambda?通常Lambda表达式是用在函数式接口上使用的.从Java8开始引入了函数式接口,其说明比较简单:函数式接口 ...

  4. Java 8新特性-1 函数式接口

    Java 8 引入的一个核心概念是函数式接口(Functional Interfaces). 通过在接口里面添加一个抽象方法,这些方法可以直接从接口中运行. 如果一个接口定义个唯一一个抽象方法,那么这 ...

  5. Java8新特性之函数式接口

    <Java 8 实战>学习笔记系列 定义 函数式接口只定义一个抽象方法,可以有多个默认方法 函数式接口的接口名上,会被@FunctionalInterface标注 作用 函数式接口的方法可 ...

  6. Java(44)JDK新特性之函数式接口

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201667.html 博客主页:https://www.cnblogs.com/testero ...

  7. JDK8新特性,给接口添加一个默认实现

    在JDK8中,允许给接口本身添加一个默认的实现.用“default”进行修饰.如下实例 package interfacetest; public interface TestInterface { ...

  8. jdk1.8新特性之函数式接口

    函数式接口就是只有一个抽象方法的接口.如果这个接口里没有或者包含了两个以上的抽象方法,对不起,你不叫函数式接口,只能叫你接口.那这个函数式有啥用呢?如果配合Lambda表达式的话,可以大大的简化代码. ...

  9. JDK8新特性:使用stream、Comparator和Method Reference实现集合的优雅排序

    大家对java接口Comparator和Comparable都不陌生,JDK8里面Comparable还和以前一样,没有什么改动:但是Comparator在之前基础上增加了很多static和defau ...

随机推荐

  1. EOJ 1058. 挤模具 (多边形面积)

    题目链接:1058. 挤模具 题意 给出模具的底和体积,求模具的高. 思路 模具的底为多边形,因此求出多边形面积,用体积除以底的面积就是答案. 多边形的面积求解见 EOJ 1127. 多边形面积(计算 ...

  2. JVM(1):Java 类的加载机制

    原文出处: 纯洁的微笑 java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang. ...

  3. Cocos2d-x之Director

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. Director类简介 在Cocos2d-x-3.x引擎中,采用节点树形结构来管理游戏对象,一个游戏可以划分为不同的场景,一个场景又可以分 ...

  4. HBase版本进化史及大版本特性

    HBase 2.0 新特性介绍 2018年4月30日HBase发布了2.0的Release版本.HBase的2.0版本承载了太多的Features,共包含4551个Issues,可以说是迄今最大的一个 ...

  5. org-mode记录总结

    org-mode记录总结 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} cod ...

  6. windows下虚拟环境的安装与创建

    使用虚拟环境的好处: 可以方便的解决不同项目对类库的依赖问题. 可以在系统中Python解释器中避免包的混乱和版本的冲突. 为每个程序单独创建虚拟环境,可以保证程序只能访问虚拟环境中的包,保持全局解释 ...

  7. python获取港股通每日成交信息

    接口:ggt_daily 描述:获取港股通每日成交信息,数据从2014年开始 限量:单次最大1000,总量数据不限制 积分:用户积2000积分可调取,5000积分无限制,请自行提高积分,具体请参阅本文 ...

  8. wait/notify方法

    执行wait方法会释放锁,执行notify不会释放锁 package com.qf.test05.pojo; /** * @author qf * @create 2018-09-18 10:41 * ...

  9. 【Luogu】【关卡2-13】线性数据结构(2017年10月)【还差一道题】

    任务说明:数组,链表,队列,栈,都是线性结构.巧用这些结构可以做出不少方便的事情. P1996 约瑟夫问题 n个人,排成环形,喊到m的人出列,输出出列顺序. 咳咳,这个题目不好写,尽管简单就是模拟题. ...

  10. mobx中使用class语法或decorator修饰器时报错

    之前课程中老师用的babel的版本比较低,我在学习时安装的babel版本较高,因此每当使用class语法或decorator修饰器时都会出现一些报错的情况! ❌ ERROR in ./src/inde ...