什么是函数式接口

援用两个中央的定义来尝试地解答下什么是函数式接口

An Interface that contains exactly one abstract method is known as functional interface. It can have any number of default, static methods but can contain only one abstract method. It can also declare methods of object class.

Functional Interface is also known as Single Abstract Method Interfaces or SAM Interfaces. It is a new feature in Java, which helps to achieve functional programming approach.

下面是javapoint)网站的定义,总结下几点

  1. 只能有一个形象函数的接口
  2. 能够有任一多默认的动态的办法
  3. 能够有Object类曾经申明的办法,因为所有的类都是Object的子类

An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface as defined by the Java Language Specification. Conceptually, a functional interface has exactly one abstract method. Since default methods have an implementation, they are not abstract. If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also does not count toward the interface's abstract method count since any implementation of the interface will have an implementation from java.lang.Object or elsewhere.

Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references.

If a type is annotated with this annotation type, compilers are required to generate an error message unless:

  • The type is an interface type and not an annotation type, enum, or class.
  • The annotated type satisfies the requirements of a functional interface.

However, the compiler will treat any interface meeting the definition of a functional interface as a functional interface regardless of whether or not a FunctionalInterface annotation is present on the interface declaration.

再来看看FunctionalInterface 中的javadoc,大差不差是一个意思,不过还是能总结出额定的一些小知识点

  1. 函数式接口的实例能够应用lambda示意,办法援用或者构造函数援用
  2. 带有这个注解的type示意这是接口,而不是注解,枚举或者类
  3. 函数式接口能够不带这个注解,然而带上了这个注解却不是函数式接口的话,编译器将会报错

自定义函数式接口

这里插一句题外话,如果上网搜寻一把函数式接口,能够发现好多常识,那当初写这篇文章仅仅是在反复的炒冷饭吗,其实不是的。网上很多文章千篇一律都是讲了java中罕用的函数式接口,就那几样,而且讲得云里雾里的,齐全不是那种新手入门的文章,至多我是看不懂。正是这样,我感觉能够写下我对函数式接口的了解,接下来会从自定义函数式接口切入。

想表白的货色很简略

  • 自定义一个IAnaimal的接口,外面只有一个形象办法talk()
  • 两个具体的实现类实现这个办法。
  • 还有主办法调用talk()

IAnimal.java

Cat.java

Dog.java

Main.java

然而有些时候不想新建一个类,比方接口比较简单,实现也不简单,新建一个类可能会冗余,此时有的同学就会想到应用匿名外部类

说到匿名外部类,那就代表能够用lambda表达式再次简化

这样一简化后IAnimal就曾经是一个函数接口了,而整个例子也就是自定义函数式接口,所以能够发现它的实质还是一个接口,只不过实现类从一个残缺的类变成了通过函数去实现。

java中罕用的函数式接口

下面讲了一个简略的自定义函数式接口的例子,接下来再看下jdk自身就申明的四大函数式接口

函数式接口参数类型返回类型用处次要办法
Consumer\<T>Tvoid生产类型为T的对象void accept(T t)
Supplier\<T>T返回类型为T的对象T get()
Function<T, R>TR操作类型为T的对象,返回R类型的对象R apply(T t)
Predicate\<T>Tboolean确定类型为T的对象是否满足束缚,返回booleanboolean test(T t)

Consumer

输入如下

Supplier

对于supplier来说,切实是找不到啥比拟好的例子,或者找到的例子都非常简略,这里略微说下supplier的懒加载个性,看下输入

Function

输入:

Predicate

输入:

破产版实现ArrayList中的forEach

可能老手同学们没太听过函数式接口,然而平时编码开发中的list里的forEach入参就是一个函数式接口

接下来参考源码实现一个破产版的List和List中的forEach,总共有以下几个步骤

  1. 新建一个Student对象
  2. 自定义一个list,外面有个Student数组存元素,还有一个add办法和forEach办法(应用Consumer)
  3. 革新办法,自定义一个函数式接口代替Consumer

Student

MyList

ForEachMain

看下输入:

IAnyway

自定义一个函数式接口,实质上就是Consumer,而后类名和办法名改了一下,这样的目标是通知老手同学jdk中的4大函数式接口不是什么神奇的货色,它们实质上就是接口,只不过是jdk总结了咱们罕用的场景来申明了这些函数式接口,防止了反复去申明一样作用的函数式接口。

定义了接口后,在来看看MyList

应用的中央也批改一下

输入:

思考

洋洋洒洒也写了一点,写完发现更迷糊了,我是晓得函数式接口是啥了,甚至在工作的编码中也强制本人用了一把函数接口,还合入了公司的代码仓。然而,什么时候什么状况下应用函数接口还始终困惑着我,包含google,baidu,statckoverflow都没有一个比拟好的答案。于目前的我而言,函数式接口仿佛和匿名外部类,和lambda表达式是一个货色。

参考文献

Java 8 Functional Interfaces - javatpoint