在前面我们学习了 lambda 表达式和函数式接口的基本概念,接下来我们再深入了解一下函数式接口。
什么是函数式接口
函数式接口也可以称为 Single Abstract Method interfaces (SAM Interfaces),只允许接口中有唯一的抽象方法。在 Java 8 提供了 @FunctionalInterface 注解,在接口不符合函数式接口要求时编译器会报错。函数式接口可以是 lambda 表达式、方法引用或者构造函数引用等等。
举个例子
@FunctionalInterface
public interface MyFirstFunctionalInterface {
public void firstWork();
}
尝试在添加一个抽象方法
@FunctionalInterface
public interface MyFirstFunctionalInterface {
public void firstWork();
public void doSomeMoreWork();
}
上面这个接口编译器将会报错
编译报错注意事项
A) 正如上面例子中,函数式接口只允许有一个抽象方法,第二个抽象方法是不允许出现在函数式接口中的。如果把 @FunctionInterface 注释去掉,编译器将不会报错,但是这个接口就不是函数式接口了。
B) @FunctionalInterface 只是一个标识,通知编译器这是一个函数式接口,当你编写的接口不符合函数式接口,编译器就会提醒你。就算不用 @FunctionalInterface 注解标识某个接口,只要这个接口符合函数式接口的规则,这个接口仍然是函数式接口。
C) 由于默认方法有实现方式,所以不是抽象的。因此可以在函数式接口中添加任意多个默认方法(你高兴就好)。
下面这个函数式接口是有效的
@FunctionalInterface
public interface MyFirstFunctionalInterface {
public void firstWork();
default void doSomeMoreWork1(){
//Method body
}
default void doSomeMoreWork2(){
//Method body
}
}
D) 如果接口中声明的是java.lang.Object
类中的 public 方法,那么这些方法不算做是函数式接口的抽象方法。因为任何一个实现接口的类都会有这些方法的默认实现,这些方法的时候可能来自于 java.lang.Object
或者其他类。Comparator
是一个函数式接口,尽管它声明了2个抽象方法,为啥呢?因为其中一个方法是是 equals() 方法,这个方法的签名和 java.lang.Object
中的 equals() 方法相同,所以不算做事抽象方法。
下面这个函数式接口任然有效
@FunctionalInterface
public interface MyFirstFunctionalInterface {
public void firstWork();
@Override
public String toString(); //Overridden from Object class
@Override
public boolean equals(Object obj); //Overridden from Object class
}
函数式接口在前面的文章中也多次提到,这里只是简单的总结了一下。
欢迎关注我的微信公众号:java初学者的日常
java初学者的日常
网友评论