【2021-07-09】接口中声明的方法只能是抽象方法么?

204 阅读2分钟

请移步至 【DobbyKim 的每日一题】 查看更多的题目~

答:

并不是。在 Java 8 发布之前,接口中所有的方法都只能是 public abstract 修饰的抽象方法,但是从 Java 8 之后,接口当中便允许有实体的默认方法,默认方法以 default 关键字声明。

如示例代码:

public interface Func {
    
    void f1();
    
    void f2();
    
    default void f3(){
        System.out.println("hello");
    }
}

为什么 Java8 以后要增加接口的默认方法呢?

考虑一个问题:

假如我使用的第三方接口,想要扩展接口的功能,于是添加一个方法,那么使用了这个第三方库的用户的代码就不可用了,原因在于:我使用的第三方接口添加了一个抽象方法,那么我实现了该接口的类就必须要实现这个新增的抽象方法,否则就会报错。这就是向后兼容性(backward compatibility)导致的问题。

Java 语言设计了单继承 + 接口这样的体系,这种设计就是为了解决像 C++ 多继承带来的二义性问题。而接口的默认方法实际上是Java 对二义性问题妥协的产物,为了增强接口的可扩展性以及满足向后兼容性,Java 不得不设计出接口的默认方法,这样既满足了接口的可扩展能力,也满足了向后兼容,用户可以在不改动代码的情况下享受软件功能的迭代升级。

不过,我们已经提过了,Java 设计出默认方法,就是对二义性问题妥协的产物。

【2021-07-09】接口中声明的方法只能是抽象方法么?

C++ 的多继承最大的缺点就是容易出现二义性。如果派生类所继承的多个父类具有相同的父类(如上图所示的菱形结构),而派生类对象需要调用祖先类的方法,就会产生二义性。

从 Java 8 开始,接口引入了默认方法,我们知道,一个类可以实现多个接口,当接口中还可以声明默认方法时,就不可避免地产生菱形继承一样的问题。

所以,Java8 接口新增的默认方法既有利,也有弊。