函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,可是能够有多个非抽象方法的接口。java
函数式接口能够被隐式转换为 lambda 表达式(箭头函数)。app
函数式接口表明的一种契约, 一种对某个特定函数类型的契约。
Lambda表达式不能脱离上下文而存在,它必需要有一个明确的目标类型(interface),而这个目标类型就是某个函数式接口。函数
java8以前已经存在的函数式接口有不少,好比java.lang.Runnable、java.util.concurrent.Callable、java.util.Comparator等。
而新增长的函数式接口都在java.util.function包下。设计
Java 不会强制要求你使用 @FunctionalInterface 注解来标记你的接口是函数式接口, 然而,做为API做者, 你可能倾向使用@FunctionalInterface指明特定的接口为函数式接口, 这只是一个设计上的考虑, 可让用户很明显的知道一个接口是函数式接口。code
先来看一个入门的例子就能明白为啥函数式接口是一种契约:对象
@FunctionalInterface public interface Predicate<T> { //该接口有一个抽象方法test,它接受一个参数t,而且返回boolean //如此定义一个抽象方法,就是在约定,我这个抽象方法的实现类,必定是仅有一个参数,而且只会返回一个boolean的值。 //因此说函数式接口是一种契约。 boolean test(T t); }
Predicate的使用实例:继承
//方法evel接受一个列表和一个Predicate接口 //list每一个元素会当成 predicate的test方法的参数。 //由于函数式接口是可使用Lambda表达式的,因此第二个参数这里就可使用箭头函数了。 public static void eval(List<Integer> list, Predicate<Integer> predicate) { //循环list for(Integer i: list) { //调用predicate的test方法,返回一个boolean值。 if(predicate.test(i)) { System.out.println(i + " "); } //疑问:Predicate是一个接口啊!那他具体执行的方法(实现类/实现方法)在哪里呢???? //请看main方法!!! } } public static void main(String args[]){ //定义一个list List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); //n -> n%2 //其实很简单,这个Lambda表达式其实就是Predicate接口的实现: // 箭头左边 n 是一个参数, 它会被传递到 Predicate 接口的 test 方法中 // 而箭头右边 n%2 其实就是这个 test 抽象方法的实现方法,它用来计算输入参数是不是一个偶数。 //因此整个方法就是用来打印list中的偶数了。 eval(list, n-> n%2 == 0 ); System.out.println("输出全部偶数:"); }
java.util.function中定义了几组类型的函数式接口以及针对基本数据类型的子接口。接口
在上面介绍中,说到函数式接口有且仅有一个抽象方法,实际上是不正确的,由于函数式接口中能够额外定义多个抽象方法,但这些抽象方法签名必须和Object类的 public 方法同样,只是咱们通常不会再从新定义这些方法。get
@FunctionalInterface public interface ObjectMethodFunctionalInterface { void count(int i); String toString(); //same to Object.toString int hashCode(); //same to Object.hashCode boolean equals(Object obj); //same to Object.equals }
函数式接口的抽象方法能够声明 可检查异常(checked exception)。 在调用目标对象的这个方法时必须catch这个异常。hash
@FunctionalInterface interface InterfaceWithException { //声明异常 void apply(int i) throws Exception; }
捕获异常:
public class FunctionalInterfaceWithException { public static void main(String[] args) { InterfaceWithException target = i -> {}; try { target.apply(10); } catch (Exception e) { e.printStackTrace(); } } }
@FunctionalInterface interface InterfaceWithException { //没有声明异常 void apply(int i); }
public class FunctionalInterfaceWithException { public static void main(String[] args) { //函数式接口没有声明异常, //而 Lambda中却抛出了异常,此时是没法经过编译的!!! InterfaceWithException target = i -> {throw new Exception();}; } }
函数式接口中除了那个抽象方法外还能够包含静态方法。
Java 8之前的规范中接口中不容许定义静态方法。 静态方法只能在类中定义。 可是到了Java 8,能够定义静态方法。
Java 8中容许接口实现方法, 而不是简单的声明, 这些方法叫作默认方法,使用特殊的关键字default。
由于默认方法不是抽象方法,因此不影响咱们判断一个接口是不是函数式接口。
BiConsumer<T,U> 表明了一个接受两个输入参数的操做,而且不返回任何结果
BiFunction<T,U,R> 表明了一个接受两个输入参数的方法,而且返回一个结果
BinaryOperator<T> 表明了一个做用于于两个同类型操做符的操做,而且返回了操做符同类型的结果
BiPredicate<T,U> 表明了一个两个参数的boolean值方法
BooleanSupplier 表明了boolean值结果的提供方
Consumer<T> 表明了接受一个输入参数而且无返回的操做
DoubleBinaryOperator 表明了做用于两个double值操做符的操做,而且返回了一个double值的结果。
DoubleConsumer 表明一个接受double值参数的操做,而且不返回结果。
DoubleFunction<R> 表明接受一个double值参数的方法,而且返回结果
DoublePredicate 表明一个拥有double值参数的boolean值方法
DoubleSupplier 表明一个double值结构的提供方
DoubleToIntFunction 接受一个double类型输入,返回一个int类型结果。
DoubleToLongFunction 接受一个double类型输入,返回一个long类型结果
DoubleUnaryOperator 接受一个参数同为类型double,返回值类型也为double 。
Function<T,R> 接受一个输入参数,返回一个结果。
IntBinaryOperator 接受两个参数同为类型int,返回值类型也为int 。
IntConsumer 接受一个int类型的输入参数,无返回值 。
IntFunction<R> 接受一个int类型输入参数,返回一个结果 。
IntPredicate :接受一个int输入参数,返回一个布尔值的结果。
IntSupplier 无参数,返回一个int类型结果。
IntToDoubleFunction 接受一个int类型输入,返回一个double类型结果 。
IntToLongFunction 接受一个int类型输入,返回一个long类型结果。
IntUnaryOperator 接受一个参数同为类型int,返回值类型也为int 。
LongBinaryOperator 接受两个参数同为类型long,返回值类型也为long。
LongConsumer 接受一个long类型的输入参数,无返回值。
LongFunction<R> 接受一个long类型输入参数,返回一个结果。
LongPredicate R接受一个long输入参数,返回一个布尔值类型结果。
LongSupplier 无参数,返回一个结果long类型的值。
LongToDoubleFunction 接受一个long类型输入,返回一个double类型结果。
LongToIntFunction 接受一个long类型输入,返回一个int类型结果。
LongUnaryOperator 接受一个参数同为类型long,返回值类型也为long。
ObjDoubleConsumer<T> 接受一个object类型和一个double类型的输入参数,无返回值。
ObjIntConsumer<T> 接受一个object类型和一个int类型的输入参数,无返回值。
ObjLongConsumer<T> 接受一个object类型和一个long类型的输入参数,无返回值。
Predicate<T> 接受一个输入参数,返回一个布尔值结果。
Supplier<T> 无参数,返回一个结果。
ToDoubleBiFunction<T,U> 接受两个输入参数,返回一个double类型结果
ToDoubleFunction<T> 接受一个输入参数,返回一个double类型结果
ToIntBiFunction<T,U> 接受两个输入参数,返回一个int类型结果。
ToIntFunction<T> 接受一个输入参数,返回一个int类型结果。
ToLongBiFunction<T,U> 接受两个输入参数,返回一个long类型结果。
ToLongFunction<T> 接受一个输入参数,返回一个long类型结果。
UnaryOperator<T> 接受一个参数为类型T,返回值类型也为T。
本文大量参考鸟窝哥,原文请移步:https://colobu.com/2014/10/28/secrets-of-java-8-functional-interface/#@FunctionalInterface