认识函数式接口

在上一节中咱们谈到Java8对原有的接口进行了加强,除此以外,Java8中还提出了一个新名词——函数式接口1(Functional Interface),用来特指某类型的接口。这类接口中定义了惟一的抽象方法,在早期这类接口被叫作SAM类型接口(single abstract interface),好比咱们常见的Runnable接口。须要注意的是接口的默认方法和静态方法并不影响一个接口成为函数式接口。java

除了早期存在的Runnable,Comparator等函数式接口以外,jdk8中又增长了java.util.function包,其中提供了经常使用的函数式接口,好比:web

  1. Predicate
  2. Function
  3. Consumer
  4. Supplier

另外,java 8中也提供了@FunctionalInterface注解用于标记一个接口是函数式接口,该注解被用来显式告知用户这是一个函数式接口,java并不强制要求要为函数式接口标记此注解。实际上一个接口是不是函数式接口由虚拟机来判断。这里咱们自行定义一个函数式接口:app

public class FunctionalInterfaceTest {
    public static void main(String[] args) {
       Calculate calculate=new Calculate() {
            @Override
            public void applay(int i) {
                System.out.println(i);
            }
        };
        calculate.applay(8);
    }

   @FunctionalInterface
    interface Calculate {
        void applay(int i);
    }
}

看完示例代码,你可能以为它和普通接口的使用也没有什么不一样,那为何java团队会提出函数式接口这个概念呢?其根本缘由在于:函数式接口彻底是为了Java 中Lambda的实现而定义的。在lambda的实现过程当中,java开发团队选择利用SAM接口做为Lambda表达式的目标类型,凡是在函数式接口出现的地方,均可以接受一个Lambda表达式做为函数式接口的实现。(Lambda表达式不能脱离上下文单独存在,它必需要有一个明确的目标类型,该目标类型也就是函数式接口)ide

到如今咱们完全明白函数式接口彻底是为实现Lambda而提出的。那如今咱们利用Lambda表达式来改写上例:svg

public class FunctionalInterfaceTest {
    public static void main(String[] args) {
        Calculate calculate = param ->System.out.println(param);
        calculate.applay(8);
    }

   @FunctionalInterface
    interface Calculate {
        void applay(int i);
    }
}

到如今为止,咱们已经认识了函数式接口,它将帮助咱们理解Lambda的使用场景。函数


  1. 也被叫作功能性接口,二者是同一回事。