钻石问题
“钻石问题”是允许多继承所带来的问题。对于允许状态的多继承语言来说(比如C++)这是一个严重的问题。但是,在Java中是不允许类的多继承,仅仅允许接口多继承,所以是不包含状态的。
考虑下面的场景:
interface A {
default void m() { ... }
}
interface B extends A {}
interface C extends A {}
class D implements B, C {}
根据上一章节说明的默认方法选择规则,在类似这种场景中Java会有一种简单直接的解释方法。
如上代码所示的这种场景,D所继承的m方法的实现是没有歧义的,因为m方法只在A中定义。如果情况改变一下,B也声明了方法m的实现,那么D就会应用“最明确的实现”这一规则。但是如果B和C都提供了m的默认实现,那么就会产生歧义,这时D就必须提供m的复写声明,可能是使用`X.super.m(..)`这种语法来显示的选择一个继承的实现。这三种情况都在上一章节的“方法决议规则”中明确说明了。
默认方法和Java中所有的方法一样,是虚拟的。这个有时会产生一些令人惊讶的结果。例如给定下面的声明:
interface A {
default void m() { System.out.println("hello from A"); }
}
interface B extends A {
default void m() { System.out.println("hello from B"); }
}
interface C extends A {}
class D implements B, C {}
下面的代码:
C c = new D();
c.m();
将会打印出
hello from B。静态的类型
C并不重要,关键的是实际的类型是
D,而D最明确的m声明是从继承B而来的。