本文概要

  1. 什么是函数式接口?
  2. 如何定义函数式接口?
  3. 常用的函数式接口
  4. 函数式接口语法注意事项
  5. 总结

1. 什么是函数式接口?

函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:SAM类型的接口(Single Abstract Method),在这个接口里面只能有一个抽象方法。

当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口。Lambda表达式只是语法糖,我们只要理解函数式接口,才能读懂和用好Lambda表达式。

2. 如何定义函数式接口?

@FunctionalInterface
public interface FunctionDemo { void get(String str);
} FunctionDemo fd = str -> System.out.println("Hello " + str);

3. 常用的函数式接口

使用Lambda表达式,一定有函数式接口的支持;但是如果我们每一个Lambda表达式都要自己创建一个接口,

这样很造成很大的不便。为了避免重复造轮子,java8常用的函数式接口都帮我们定义好,拿来直接使用即可。

如果这些常用的接口不能满足需求时,这时才需要 自定义函数式接口。

下面是我们常用的几类函数式接口:

  • 消费性函数式接口

特点:接受一个或者多个参数,没有返回值

  • 供给型函数式接口

特点:没有参数(无参),提供返回值

  • 函数型函数式接口

特点:接收一个或者多个参数,有返回值

  • 断定性函数式接口

特点:接收一个或者多个参数,返回一个boolean类型

@Test
public void testCoreInter(){
/**
* @name 消费型接口
* @use Consumer<T>
* @param T 传入参数
* @fun 接受一个参数 无返回值
* */
Consumer<String> con=(str)->System.out.println(str);
con.accept("我是消费型接口!"); /**
* @name 供给型接口
* @use Supplier<R>
* @param R 返回值类型
* @fun 无参数 有返回值
* */
Supplier<Date> supp=()-> new Date();
Date date=supp.get();
System.out.println("当前时间:"+date); /**
* @name 函数型接口
* @use Function<T,R>
* @param T 传入参数
* @return R 返回值类型
* @fun 接受一个参数 有返回值
* */
Function<String, String> fun=(str)->"hello,"+str;
String str=fun.apply("张俊强");
System.out.println(str); /**
* @name 断定型接口
* @use Predicate<T>
* @param T 传入参数
* @return Boolean 返回一个Boolean型值
* @fun 接受一个参数 返回Boolean型值
* */
Predicate<Integer> pre=(num)->num>0;
Boolean flag=pre.test(10);
System.out.println(flag);
}

比如方法foreach(),入参为Consumer

default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}

4. 函数式接口语法注意事项

从SAM原则上讲,这个接口中,只能有一个函数需要被实现,但是也可以有如下例外:

  • 默认方法:必须用default修饰,且只能是public,默认也是public。

它也是作为一种向后兼容能力而出现,旧的接口也能用到Lambda表达式中。例如,List或Collection接口是没有forEach方法的声明的。Java 8引入默认方式使得List和Collection接口能够拥有forEach方法的默认实现。实现了这些接口的类也不必再实现相同的功能了。

语法如下所示:

@FunctionalInterface
interface A {
default void test() {
System.out.println("接口A的默认方法");
}
void test1();
}
  • 静态方法

函数式接口中可以有静态方法,一个或者多个静态方法不会影响SAM接口成为函数式接口,并且静态方法可以提供方法实现

@FunctionalInterface
interface TestStaticMethod {
//这是一个抽象方法
void test();
//静态方法,不是抽象方法
static void test1() {
System.out.println("接口里的静态方法!");
}
}

      

      

      

  • 如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。
 If an interface declares an abstract method overriding one of the public methods of {@code java.lang.Object},
that also doesnot count toward the interface's abstract method count
since any implementation of the interface will have an implementation from {@code java.lang.Object} or elsewhere. @FunctionalInterface
public interface DemoFunctionalInterface{
void action(); //Object's public methods
String toString();
int hashCode();
boolean equals(Object o);
}
  • 注解@FunctionalInterface不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错

5. 总结

  • 函数式接口只能包含一个抽象方法
  • 函数式接口可以包含Object类中所有public修饰的方法
  • 函数工接口可以包含一个或多个静态方或默认方法

参考文献


tips:本文属于自己学习和实践过程的记录,很多图和文字都粘贴自网上文章,没有注明引用请包涵!如有任何问题请留言或邮件通知,我会及时回复。

java8新特性学习:函数式接口的更多相关文章

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

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

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

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

  3. Java8 新特性学习 Lambda表达式 和 Stream 用法案例

    Java8 新特性学习 Lambda表达式 和 Stream 用法案例 学习参考文章: https://www.cnblogs.com/coprince/p/8692972.html 1.使用lamb ...

  4. java8 新特性学习笔记

    Java8新特性 学习笔记 1主要内容 Lambda 表达式 函数式接口 方法引用与构造器引用 Stream API 接口中的默认方法与静态方法 新时间日期 API 其他新特性 2 简洁 速度更快 修 ...

  5. java8新特性学习1

    java8增加了不少新特性,下面就一些常见的新特性进行学习... 1.接口中的方法 2.函数式接口 3.Lambda表达式 4.java8内置的四大核心函数式接口 5.方法引用和构造器引用 6.Str ...

  6. java8新特性学习:stream与lambda

    Streams api 对 Stream 的使用就是实现一个 filter-map-reduce 过程,产生一个最终结果,或者导致一个副作用(side effect). 流的操作类型分为两种: Int ...

  7. Java8 新特性学习

    摘自:https://blog.csdn.net/shuaicihai/article/details/72615495 Lambda 表达式 Lambda 是一个匿名函数,我们可以把 Lambda ...

  8. java8新特性学习2

    六.Stream API Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API(java.util.stream.*).Stream 是 Java8 中 ...

  9. Java8新特性:函数式编程

    1. 概述 函数式编程学习目的: 能够看懂公司里的代码 大数据量下处理集合效率更高 代码可读性高 消灭嵌套地狱 函数式编程思想: 面向对象思想需要关注用什么对象完成什么事情.而函数式编程思想就类似于我 ...

随机推荐

  1. [bzoj4842][bzoj1283][Neerc2016]Delight for a Cat/序列_线性规划_费用流

    4842: [Neerc2016]Delight for a Cat_1283: 序列 题目大意:ls是一个特别堕落的小朋友,对于n个连续的小时,他将要么睡觉要么打隔膜,一个小时内他不能既睡觉也打隔膜 ...

  2. Ansj与hanlp分词工具对比

    一.Ansj 1.利用DicAnalysis可以自定义词库: 2.但是自定义词库存在局限性,导致有些情况无效: 比如:“不好用“的正常分词结果:“不好,用”. (1)当自定义词库”好用“时,词库无效, ...

  3. Oracle-DQL 3- 单行函数

    单行函数: --使用函数对表中的数据进行运算和处理,针对每行数据返回一个结果,叫做单行函数--包括数字函数,字符函数,日期函数,转换函数,其他函数 1.数字函数 --round(m,n) 将数字m精确 ...

  4. Luogu P4426 [HNOI/AHOI2018]毒瘤

    题目 神仙题. 首先我们可以把题意转化为图的独立集计数.显然这个东西是个NP-Hard的. 然后我们可以注意到\(m\le n+10\),也就是说最多有\(11\)条非树边. 我们现在先考虑一下,树上 ...

  5. POJ - 3687 Labeling Balls (拓扑)

    (点击此处查看原题) 题意 此处有n盏灯,编号为1~n,每盏灯的亮度都是唯一的,且在1~n范围之间,现已知m对灯之间的关系:a b ,说明灯a的亮度比灯b小,求出每盏灯的亮度,要求字典序最小(编号小的 ...

  6. python3列表、元组

    列表.元组操作 列表是我们最以后最常用的数据类型之一,通过列表可以对数据实现最方便的存储.修改等操作.列表中的每个元素都分配一个数字也就是它的位置,或叫索引,第一个索引是0,第二个索引是1,依此类推. ...

  7. Tensorflow加载预训练模型和保存模型

    转载自:https://blog.csdn.net/huachao1001/article/details/78501928 使用tensorflow过程中,训练结束后我们需要用到模型文件.有时候,我 ...

  8. 并不对劲的复健训练-bzoj5249:loj2472:p4364[2018多省联考]IIIDX

    题目大意 给出\(n,k,d_1,...,d_n\)(\(n\leq 5\times 10^5,1<k\leq 10^9,d\leq 10^9,k\in R\)).有一个满足 对于每个点\(i\ ...

  9. 快速上手小程序的mpvue框架

    一.什么是mpvue框架? mpvue 是一个使用 Vue.js 开发小程序的前端框架.框架基于 Vue.js 核心(所以建议熟练掌握vue再使用mpvue框架,否则还是建议去使用原生框架去写小程序) ...

  10. 28-Perl POD 文档

    1.Perl POD 文档Perl 中可以在模块或脚本中嵌入 POD(Plain Old Documentation) 文档.POD 是一种简单而易用的标记型语言(置标语言).POD 文档使用规则: ...