Java8的函数式接口你真的了解吗?

FunctionalInterface
FunctionalInterface

函数式接口

若是你的好奇心使你翻看Runnable接口源代码,你会发现该接口被一个@FunctionalInterface的注解修饰,这是 Java 8 中添加的新注解,用于表示 函数式接口java

FunctionalInterface-Runnable
FunctionalInterface-Runnable

函数式接口又是什么鬼?

在 Java 8 中,把那些仅有一个抽象方法的接口称为函数式接口。若是一个接口被@FunctionalInterface注解标注,表示这个接口被设计成函数式接口,只能有一个抽象方法,若是你添加多个抽象方法,编译时会提示“Multiple non-overriding abstract methods found in interface XXX”之类的错误。markdown

标注为 FunctionalInterface 的接口被称为函数式接口,该接口只能有一个自定义方法,可是能够包括从 object 类继承而来的方法。若是一个接口只有一个方法,则编译器会认为这就是一个函数式接口。是不是一个函数式接口,须要注意的有如下几点:app

  • 该注解只能标记在”有且仅有一个抽象方法”的接口上。
  • JDK8 接口中的静态方法和默认方法,都不算是抽象方法。
  • 接口默认继承 java.lang.Object,因此若是接口显示声明覆盖了 Object 中方法,那么也不算抽象方法。
  • 该注解不是必须的,若是一个接口符合”函数式接口”定义,那么加不加该注解都没有影响。加上该注解可以更好地让编译器进行检查。若是编写的不是函数式接口,可是加上了@FunctionInterface,那么编译器会报错。
  • 在一个接口中定义两个自定义的方法,就会产生 Invalid ‘@FunctionalInterface’ annotation; FunctionalInterfaceTest is not a functional interface 错误.

函数式方法又能作什么?

Java8 容许你以 Lambda 表达式的方式为函数式接口提供实现,通俗的说,你能够将整个 Lambda 表达式做为接口的实现类ide

除了Runnable以外,Java 8 中内置了许多函数式接口供开发者使用,这些接口位于java.util.function包中。如:函数

Functional-Package
Functional-Package
name type result desc
Consumer Consumer T -> void 接收 T 对象,不返回值
Predicate Predicate T -> boolean 接收 T 对象并返回 boolean
Function Function<T, R> T -> R 接收 T 对象,返回 R 对象
Supplier Supplier void -> T 提供 T 对象(例如工厂),不接收值
UnaryOperator UnaryOperator T -> T 接收 T 对象,返回 T 对象
BinaryOperator BinaryOperator T, T -> T 接收两个 T 对象,返回 T 对象

若是输入参数是基本类型,为了不自动拆箱装箱,能够使用其余基本类型的函数接口。oop

Function

interface Function<T, R> 接口包含一个apply方法、两个默认方法(composeandThen)和一个静态方法identityapply是接口的基本方法。 composeandThen是一对儿方法,他们的区别在于执行的顺序不一样。ui

//返回一个先执行before函数对象apply方法再执行当前函数对象apply方法的函数对象
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
}
复制代码
//返回一个先执行当前函数对象apply方法再执行after函数对象apply方法的函数对象。
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
}
复制代码
// 根据上面的解释想一下执行结果
Function<Integer, Integer> name = e -> e * 2;
Function<Integer, Integer> square = e -> e * e;
int value = name.andThen(square).apply(3);
int value2 = name.compose(square).apply(3);
//返回一个执行了apply()方法以后只会返回输入参数的函数对象
Object identity = Function.identity().apply("Test");
复制代码

Consumer

interface Consumer<T> 接口包含一个void accept(T t);方法、默认方法andThen.spa

default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    return (T t) -> { accept(t); after.accept(t); };
}
复制代码

只有一个默认方法也是和它的返回类型有关系,由于返回的是 void。.net

Predicate

interface Predicate<T>接口包含一个boolean test(T t);方法,三个默认方法(andnegate,or),还有一个静态方法。 咱们也知道 Predicate 接口是返回 boolean 类型的,因此一看就知道是条件判断的。 举几个栗子吧:设计

String name = "hello";
Predicate<String> predicate = x -> x.equals("hello");
Predicate<String> predicate2 = x -> x.length() < 2;
// and 多个Predicate条件并的关系判断,第一个为false就不往下走了,知足短路原则
System.out.println(predicate.and(predicate2).test(name));
// or 多个Predicate条件或的关系判断,一样知足短路原则
System.out.println(predicate.or(predicate2).test(name));
// negate 取反的意思,就是否的条件判断
System.out.println(predicate.and(predicate2.negate()).test(name));
// isEqual 静态方法,判断是否相等
System.out.println(Predicate.isEqual(name).test(name));
复制代码

Supplier

Supplier只有一个 get()方法。 咱们来看看几个栗子:

Supplier<String> supplier = () -> "hello world";
//get方法不接受参数,返回一个结果
System.out.println("supplier = [" + supplier.get() + "]");
 //替代不接受参数的工厂方法 Supplier<Student> studentSupplier = () -> new Student(); System.out.println(studentSupplier.get());  //由于Student的构造方法不接受参数,返回一个结果,符合Supplier接口的要求,能够简写以下: Supplier<Student> studentSupplier2 = Student::new; 复制代码

总结

函数式接口其实差异不大,只是参数和返回的不一样,只要想明白其中的一种,其余的也就懂了。

参考

JDK8 新特性-java.util.function-Function 接口[1]

Java8 的一些新特性 java.util.function 包[2]

Java JVM(七):Function,Consumer,Predicate 接口[3]


求关注、分享、在看!!! 你的支持是我创做最大的动力。

Reference

[1]

JDK8新特性-java.util.function-Function接口: https://blog.csdn.net/huo065000/article/details/78964382

[2]

Java8的一些新特性 java.util.function包: https://blog.csdn.net/hxg117/article/details/77029930

[3]

Java JVM(七):Function,Consumer,Predicate 接口: https://blog.csdn.net/pzxwhc/article/details/48314039

本文使用 mdnice 排版