什么是函数式接口

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

  1. Thread t1 = new Thread(new Runnable() {
  2. @Override
  3. public void run() {
  4. System.out.println("t1");
  5. }
  6. });
  7. t1.start();

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

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

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

  1. @FunctionalInterface
  2. public interface Runnable {
  3. public abstract void run();
  4. }

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

  1. @Documented
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target(ElementType.TYPE)
  4. public @interface FunctionalInterface {
  5. }

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

内置函数式接口

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

  1. //Consumer<T> - T作为输入,执行某种动作但没有返回值
  2. Consumer<String> con = (x) -> {
  3. System.out.println(x);
  4. };
  5. con.accept("hello world");
  6. //Supplier<T> - 没有任何输入,返回T
  7. Supplier<String> supp = () -> {
  8. return "Supplier";
  9. };
  10. System.out.println(supp.get());
  11. //Predicate<T> -T作为输入,返回的boolean值作为输出
  12. Predicate<String> pre = (x) -> {
  13. System.out.print(x);
  14. return x.startsWith("op");
  15. };
  16. System.out.println(": " + pre.test("op, hello World"));
  17. // Function<T, R> -T作为输入,返回的R作为输出
  18. Function<String, String> function = (x) -> {
  19. System.out.print(x + ": ");
  20. return "Function";
  21. };
  22. System.out.println(function.apply("hello world"));
  23. //BinaryOperator<T> -两个T作为输入,返回一个T作为输出,对于“reduce”操作很有用
  24. BinaryOperator<String> bina = (x, y) -> {
  25. System.out.print(x + " " + y);
  26. return "BinaryOperator";
  27. };
  28. System.out.println(" " + bina.apply("hello ", "world"));

自定义函数式接口

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

  1. @FunctionalInterface
  2. public interface CalcInterface<N, V> {
  3. V operation(N n1, N n2);
  4. }

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

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

  1. public static class NumberOperation<N extends Number, V extends Number> {
  2. private N n1;
  3. private N n2;
  4. public NumberOperation(N n1, N n2) {
  5. this.n1 = n1;
  6. this.n2 = n2;
  7. }
  8. public V calc(CalcInterface<N, V> ci) {
  9. V v = ci.operation(n1, n2);
  10. return v;
  11. }
  12. }

3、测试函数式接口

  1. private static void testOperationFnInterface() {
  2. NumberOperation<Integer, Integer> np = new NumberOperation(13, 10);
  3. CalcInterface<Integer, Integer> addOper1 = (n1, n2) -> {
  4. return n1 + n2;
  5. };
  6. CalcInterface<Integer, Integer> multiOper1 = (n1, n2) -> {
  7. return n1 * n2;
  8. };
  9. System.out.println(np.calc1(addOper1));
  10. System.out.println(np.calc1(multiOper1));
  11. // 上面的可以简写为
  12. System.out.println(np.calc1((n1, n2) -> n1 + n2));
  13. System.out.println(np.calc1((n1, n2) -> n1 * n2));
  14. }

最后输出:

  1. 23
  2. 130
  3. 23
  4. 130

函数式接口规范

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

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

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

举例说明

正确的函数式接口。

  1. @FunctionalInterface
  2. public interface CalcInterface<N, V> {
  3. V operation(N n1, N n2);
  4. }

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

  1. @FunctionalInterface
  2. public interface CalcInterface<N, V> {
  3. V operation(N n1, N n2);
  4. public boolean equals(Object object);
  5. public default void defaultMethod() {
  6. }
  7. public static void staticMethod() {
  8. }
  9. }

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

  1. public interface CalcInterface<N, V> {
  2. V operation(N n1, N n2);
  3. V operation2(N n1, N n2);
  4. }

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

  1. @FunctionalInterface
  2. public interface CalcInterface<N, V> {
  3. V operation(N n1, N n2);
  4. V operation2(N n1, N n2);
  5. }

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

  1. public interface CalcInterface<N, V> {
  2. }

推荐阅读

干货:免费领取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. how to catch error in make error message

    make 2>&1 | grep error -C 10 -n

  2. OO七大设计原则

    一.单一职责原则(Single Responsibility Principle,SRP) 含义: 1.避免相同的职责分散到不同的类中 2.避免一个类承担太多职责 作用: 1.可以减少类之间的耦合 2 ...

  3. csdn加入暂时会话功能

    版权声明:本文为博主原创文章.若要转载请注明出处! ^_^ https://blog.csdn.net/u010892841/article/details/25334153             ...

  4. MVC5+EF6 完整教程

    随笔分类 - MVC ASP.NET MVC MVC5+EF6 完整教程17--升级到EFCore2.0 摘要: EF Core 2.0上周已经发布了,我们也升级到core 文章内容基于vs2017, ...

  5. Python第九节 条件和循环

    while...else 当满足while循环条件的时候执行循环体内的语句,否则执行else的语句例如下面的例子: count = 1 while count <= 5: print(" ...

  6. 配置ssh免密登录问题

    有小伙伴的系统需要做免密登录.配置比较简单,ssh-keygen然后生成authorized_keys 文件即可. 但是配置好之后,修改相应用户的家目录权限后,则免密登录就失效了. 经过试验,发现家目 ...

  7. SpringMVC以及SSM整合

    本人才疏学浅,如有错误欢迎批评!转载请注明出处:https://www.cnblogs.com/lee-yangyaozi/p/11226145.html SpringMVC概述 Spring Web ...

  8. windows如何在当前路径下快速打开cmd

    直接在打开的文件夹地址栏当中输入cmd即可.

  9. 【LeetCode】Heap

    [215] Kth Largest Element in an Array [Medium] 给个无序数组,返回第K大的数字. 方法1. 直接使用优先队列 priority_queue class S ...

  10. Spring 整合 Redis(转)

    转自http://blog.csdn.net/java2000_wl/article/details/8543203 pom构建: <modelVersion>4.0.0</mode ...