本文概要

  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. java.lang.ClassNotFoundException: org.apache.commons.dbutils.ResultSetHandle

    原因是这两个地方都得导入dbutils的jar包,一般出错是因为WEB-INF下没有导入包,记得导入,然后buildPath即可

  2. Scala 内部类及外部类

    转自:https://blog.csdn.net/yyywyr/article/details/50193767 Scala内部类是从属于外部类对象的. 1.代码如下 package com.yy.o ...

  3. MySql 多表关系

    多表关系 一对一关系 一对一关系是最好理解的一种关系,在数据库建表的时候可以将人表的主键放置与身份证表里面,也可以将身份证表的主键放置于人表里面 一对多关系 班级是1端,学生是多端,结合面向对象的思想 ...

  4. http请求之of_ordering_http_get

    //Public function of_ordering_http_get (string as_url) returns string //string as_urllong ll_tempstr ...

  5. mysql内存优化

    一.环境说明: 操作系统:CentOS 6.5 x86_64 数据库:Mysql 5.6.22 服务器:阿里云VPS,32G Mem,0 swap 二.问题情况: 1.某日发现公司线上系统的Mysql ...

  6. 怎样在 Vue 中使用 v-model 处理表单?

    主要是通过 v-model 对表单元素做数据的 双向绑定. 用法其实也很简单, 只是因为表单元素有不同类型, 处理方式有些许不同, 这点需要注意. 1. 如果是 输入框 , 可以直接使用 v-mode ...

  7. 使用Enablebuffering多次读取Asp Net Core 请求体

    使用Enablebuffering多次读取Asp Net Core 请求体 1 .Net Core 2.X时代 使用EnableRewind倒带 public IActionResult Index( ...

  8. 【原创】大叔问题定位分享(34)Spring的RestTemplate请求json数据后内容被修改

    先看代码 org.springframework.web.client.RestTemplate public RestTemplate() { this.messageConverters = ne ...

  9. 简单了解soap协议

    SOAP的是什么的简写 soap是(Simple Object Access Protocal)的简写,即简单对象访问协议,它描述了一种在分散或分布式的环境中如何交换信息的轻量级协议. soap用来干 ...

  10. LeetCode:182.查找重复的电子邮箱

    题目链接:https://leetcode-cn.com/problems/duplicate-emails/ 题目 编写一个 SQL 查询,查找 Person 表中所有重复的电子邮箱. 示例: +- ...