Java里的函数式接口
函数式接口是在Java8里跟随lambda表达式一起提出的,学习lambda表达式之前,还是先了解一下什么是“函数式接口”。
- 概念
函数式接口就是指只含有一个抽象函数的接口。这个接口里可以包含任意多个默认方法,任意多个静态方法。函数式接口可以使用注解@FunctionalInterface标注,如果被标注的接口不符合条件,在编译器里会提示错误。
@FunctionalInterface public interface FunInterface { /** * 抽象方法 */ void abstractSay(); /** * 默认方法 */ default void defaultSay() { System.out.println("defaultSay"); } /** * 静态方法 */ static void staticSay() { System.out.println("staticSay");
如上面的例子所示,自定义的接口FunInterface就是一个函数式接口,并且使用了注解标注。这个接口里定义了一个默认方法和一个静态方法,都没有影响它是一个函数式接口的本质。
- 注意事项
函数式接口和普通的接口一样,可以有实现类。
public class FunInterfaceImpl implements FunInterface { @Override public void abstractSay() { System.out.println("abstractSay"); } }
函数式接口的条件是只含有一个抽象方法,所以如果存在接口继承,要求继承下来的所有方法中只能有一个抽象方法。
@FunctionalInterface public interface SubFunInterface extends FunInterface { /** * 子类的抽象方法 */ void subAbstractSay(); }
子接口SubFunInterface中也声明了一个抽象方法subAbstractSay,又从父类FunInterface中继承了抽象方法abstractSay,所以不再满足函数式接口的条件,因此使用注解@FunctionalInterface将会提示错误!
函数式接口的抽象方法如果覆盖Object类中的public方法,那么不算在“函数式接口只含有一个抽象方法”限制之内。
@FunctionalInterface public interface FunInterface { /** * 抽象方法 */ void abstractSay(); /** * 覆盖了Object.toString()方法 * @return */ String toString(); /** * 默认方法 */ default void defaultSay() { System.out.println("defaultSay"); } /** * 静态方法 */ static void staticSay() { System.out.println("staticSay"); } }
这个代码在上面的例子里又新增了一个抽象方法toString,但是使用注解@FunctionalInterface仍然没错,它仍是一个函数式接口。因为这里的toString方法是覆盖的Object类中的public方法。另外,看下面的代码块:
@FunctionalInterface public interface FunInterface { /** * 抽象方法 */ void abstractSay(); /** * 覆盖了Object.toString()方法 * @return */ String toString(); /** * 覆盖了Object.clone()方法 * 但是不是public 而是protected * @return */ Object clone(); /** * 默认方法 */ default void defaultSay() { System.out.println("defaultSay"); } /** * 静态方法 */ static void staticSay() { System.out.println("staticSay"); } }
这个函数式接口就是错误的,因为包含了多个抽象方法,虽然clone()方法来自Object类,但是这不是一个public方法,因为不能算作“例外”。