函数式接口
关于函数式接口,见过最多的一句话就是:“函数式接口是一种仅仅只有一个抽象方法的接口”,这种描述并不对。实际上,这里所指的一个抽象方法,是指除了来自Object
的方法,见测试如下:
package com.duofei.function.basic;
/**
* 多个方法的接口
* @author duofei
* @date 2019/7/8
*/
@FunctionalInterface
public interface MoreMethods extends OneMethod{
//void get();
// a
// void getOne();
/** b
* 来自Object 的public方法
* @author hxf
* @date 2019/7/8
* @param
* @return
* @throws
*/
@Override
boolean equals(Object obj);
/**
* c : 测试时,无法将该类标记为 FunctionalInterface
* 来自Object 的protected方法
* @author hxf
* @date 2019/7/8
* @param
* @return
* @throws
*/
// Object clone() throws CloneNotSupportedException;
/**
* d : 来自Object 的public方法
* @author hxf
* @date 2019/7/8
* @param
* @return
* @throws
*/
@Override
String toString();
/**
* e: 无法将该接口标记为FunctionalInterface
* @author hxf
* @date 2019/7/8
* @param
* @return
* @throws
*/
//void finalize() throws Throwable;
}
这里能够看见的是 该接口依然能够使用FunctionalInterface 注解,所以当接口声明了Object的公共的非原生方法时,该接口依然是函数式接口。可以参照 JDK 源码中的 Comparator
接口。
为什么在接口中声明 Object 的方法,会有这样特殊的限制呢?以及为什么需要加Override 注解呢?
在 Java 编程思想中有这样的一段话,“可以使用接口类型的引用调用任何
Object
的方法,因为不管对象接口怎样实现接口,它始终是一个Object
,事实上,任何没有隐式扩展其他接口的接口都有匹配Object
的每个公共方法的成员(除非接口显式地覆盖它们) 。上面的话也就是说实际上这些方法已经有了方法体,这和JDK8中在接口里声明默认方法或者静态方法一样,该接口依然能给被标记为函数式接口。
boolean equals(Object)
是抽象方法的显示声明,否则将隐式声明该抽象方法,并将有实现接口的每个类自动实现。
Override
注解表明一个方法声明旨在重写父类的方法声明。文档里有写在两种情况下,需要该注解,否则会生成编译时的错误信息:
- 方法重写或者实现了一个在父类中的方法声明
- 该方法有一个覆盖的签名-相当于在
Object
中声明的任何公共方法的签名第二种情况也就说明了为什么需要加该注解。
除了通常通过声明和实例化一个类来创建接口实例的过程之外,还可以使用方法引用表达式和lambda表达式来创建函数式接口。
// 在MoreMethods接口中声明
List getOne();
// 那么可以有如下的写法:
MoreMethods m = ArrayList::new;
MoreMethods m2 = Arrays::asList;