[英]How does jvm react to this
interface CanFight {
void fight();
}
interface CanSwim {
void swim();
}
interface CanFly {
void fly();
}
class ActionCharacter {
public void fight() {
System.out.println("Inside class fight");
}
}
class Hero extends ActionCharacter
implements CanFight, CanSwim, CanFly {
public void swim() {}
public void fly() {}
}
public class MultipleInterface {
public static void t(CanFight x) { x.fight(); }
public static void u(CanSwim x) { x.swim(); }
public static void v(CanFly x) { x.fly(); }
public static void w(ActionCharacter x) { x.fight(); }
public static void main(String[] args) {
Hero h = new Hero();
t(h); // Treat it as a CanFight
u(h); // Treat it as a CanSwim
v(h); // Treat it as a CanFly
w(h); // Treat it as an ActionCharacter
}
}
如何JVM表现得像我不是从实现方法canFight
接口,但它需要从ActionCharacter
类? 它背后的逻辑是什么? canFight()
是我没有定义方法fight()
,如果实现canFight()
接口必须完成。
它不是JVM,而是Java编译器。 (如果JVM发现缺少的方法应该存在,那么你会得到一个NoSuchMethodException,但编译器不会让你达到那个点,除非你欺骗它)。
至于你的问题,声明方法的类或超类或接口无关紧要,只需要匹配名称和签名。 因此, CanFight#fight
ActionCharacter#fight
和CanFight#fight
声明了同样的事情。 Java在两者之间没有区别(既不是编译器也不是JVM /字节码格式)。
你的Hero
继承fight
从ActionCharacter
,但因为它正好也匹配定义的方法CanFight
,还兼作该接口的实现。
可以更清楚要么改变方法名(如果这些都应该是两种不同的方法),要么有ActionCharacter
还实现CanFight
(如果这确实是有意相同的方法)。
如果一个类型实现两个接口,并且每个接口定义一个具有相同签名的方法,那么实际上只有一个方法,并且它们是不可区分的。
例如,如果两种方法具有冲突的返回类型,那么它将是编译错误。 这是继承,方法重写,隐藏和声明的一般规则,并且还适用于不仅可能在2个继承的接口方法之间发生冲突,还可以应用于接口和超类方法之间的冲突,甚至只是由于泛型的类型擦除引起的冲突。
它在JLS中说过
允许类中的单个方法声明实现多个超接口的方法。
您正在扩大ActionCharacter
这意味着你希望所有的操作和属性ActionCharacter
继承你的Hero
类。
这也包括fight
行动。 你记住Hero
为实现CanFight
但你继承从实际执行ActionCharacter
。
Hero需要实现void figth();
但它继承了void figth();
来自ActionCharacter,因此符合要求。
接口只声明一个方法,不能在接口中定义方法。 那么这意味着您要在接口中提供要实现的内容的草稿。
现在,你的类Hero继承了ActionCharacter类,它有一个public void fight()的定义。 但是,这个fight()与CanFight的fight()无关。 所以如果你在Hero中定义一个fight(),你将覆盖ActionCharacter的fight()。
由于你也实现了CanFight接口,jvm将允许你在CanFight中声明方法,但它将被视为ActionCharacter的fight()的覆盖。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.