这两天在重写排序规则时发现 Comparator
中有 “两个抽象方法”,即 compare
和 equals
。这令我十分费解,函数式接口不是只能一个抽象方法吗?(具体方法、default 方法不算在内)
直到看到 @FunctionalInterface 的 JDK 文档注释 才解决了我的疑惑。
-
如果一个接口中声明的抽象方法是重写了超类
Object
类中任意一个 public 方法,那么这些抽象方法并不会算入接口的抽象方法数量中。因为任何接口的实现都会从其父类Object
或其它地方获得这些方法的实现。- 接口也继承了
Object
,所以在接口中定义equals
方法本质上是对Object
的重写(抽象重写具体)。 - 如果一个类同时继承父类,并且实现接口,且它们有重名方法,此时采用超类优先
- 接口也继承了
/**
* @Author: posper
* @Date: 2022/07/20 15:49
*/
public class Test {
public static void main(String[] args) {
Animal dog = new Dog();
// 超类优先,所以这里调用的是父类 Animal 中的 run() 方法
dog.run();
}
}
// 验证“超类优先原则”,见 main() 中 dog.run() 方法.
class Dog extends Animal implements Run {
int age;
String name;
}
// 接口
@FunctionalInterface
interface Run {
void run();
// 这里类比 Comparator 中的 equals,`@FunctionalInterface` 不会将其不算作抽象方法
@Override
boolean equals(Object o);
}
// 父类
class Animal {
public void run() {
System.out.println("调用Animal的run()方法");
}
}
// 验证“抽象重写具体”
abstract class Cat extends Animal {
// 抽象重写具体方法,可以是可以但是感觉没啥必要...
@Override
public abstract void run();
}
运行结果: