具有相同方法名称和签名的两个接口。但是由单个类实现,那么编译器将如何识别哪个方法用于哪个接口?
前任:
interface A{ int f(); } interface B{ int f(); } class Test implements A, B{ public static void main(String... args) throws Exception{ } @Override public int f() { // from which interface A or B return 0; } }
如果一个类型实现了两个接口,并且每个接口都interface定义了一个签名相同的方法,那么实际上只有一个方法,并且它们是不可区分的。例如,如果这两个方法的返回类型冲突,那么这将是一个编译错误。这是继承、方法覆盖、隐藏和声明的一般规则,并且不仅适用于两个继承interface方法之间的可能冲突,也适用于一个interface和一个超级class方法之间的冲突,甚至只是由于泛型的类型擦除引起的冲突。
interface
class
这是一个示例,其中您有一个interface Gift,它有一个present()方法(例如,赠送礼物),还有一个interface Guest,它也有一个present()方法(例如,客人在场并且没有缺席)。
interface Gift
present()
interface Guest
Presentable johnny既是 aGift又是 a Guest。
Presentable johnny
Gift
Guest
public class InterfaceTest { interface Gift { void present(); } interface Guest { void present(); } interface Presentable extends Gift, Guest { } public static void main(String[] args) { Presentable johnny = new Presentable() { @Override public void present() { System.out.println("Heeeereee's Johnny!!!"); } }; johnny.present(); // "Heeeereee's Johnny!!!" ((Gift) johnny).present(); // "Heeeereee's Johnny!!!" ((Guest) johnny).present(); // "Heeeereee's Johnny!!!" Gift johnnyAsGift = (Gift) johnny; johnnyAsGift.present(); // "Heeeereee's Johnny!!!" Guest johnnyAsGuest = (Guest) johnny; johnnyAsGuest.present(); // "Heeeereee's Johnny!!!" } }
上面的代码片段编译并运行。
请注意, 只有一个 @Override 必要!. 这是因为Gift.present()和Guest.present()是“ -等价的@Override”(JLS 8.4.2)。
@Override
Gift.present()
Guest.present()
因此,johnny 只有一个实现 ,present()无论您如何对待johnny,无论是作为 aGift还是作为 a Guest,都只有一种方法可以调用。
johnny
这是一个示例,其中两个继承的方法不@Override等效:
public class InterfaceTest { interface Gift { void present(); } interface Guest { boolean present(); } interface Presentable extends Gift, Guest { } // DOES NOT COMPILE!!! // "types InterfaceTest.Guest and InterfaceTest.Gift are incompatible; // both define present(), but with unrelated return types" }
这进一步重申了从 an 继承成员interface必须遵守成员声明的一般规则。在这里,我们有Gift并Guest定义present()了不兼容void的返回类型:一个另一个boolean。出于同样的原因,您不能在一个类型中使用void present()和boolean present(),此示例会导致编译错误。
void
boolean
void present()
boolean present()
您可以继承@Override等效的方法,但要符合方法覆盖和隐藏的通常要求。由于它们 是 @Override等效的,因此实际上只有一种方法可以实现,因此没有什么可区分/选择的。
编译器不必确定哪个方法适用于哪个接口,因为一旦确定它们是@Override等效的,它们就是相同的方法。
解决潜在的不兼容性可能是一项棘手的任务,但这完全是另一个问题。