3
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
  }
}

当我没有从canFight接口实现方法而是从ActionCharacter类中获取方法时,JVM 的行为如何?其背后的逻辑是什么?关键是我没有定义实现接口时fight()必须完成的方法。canFight()

4

5 回答 5

3

与其说是 JVM,不如说是 Java 编译器。(如果 JVM 发现应该存在的方法丢失,你会得到一个 NoSuchMethodException,但除非你欺骗它,否则编译器不会让你到达那个点)。

至于您的问题,在哪个类或超类或接口中声明方法无关紧要,只需要名称和签名匹配。因此,ActionCharacter#fightCanFight#fight声明同样的事情。Java 对两者没有区别(编译器和 JVM/字节码格式都没有)。

Hero继承fightActionCharacter,但由于它恰好也与 中定义的方法匹配CanFight,因此它也兼作该接口的实现。

更改方法名称(如果它们应该是两种不同的方法)或ActionCharacter还实现CanFight(如果这确实是相同的方法)可能会更清楚。

于 2013-03-25T06:19:20.097 回答
2

如果一个类型实现了两个接口,并且每个接口定义了一个签名相同的方法,那么实际上只有一个方法,并且它们是不可区分的。

比如说,如果这两个方法的返回类型有冲突,那么这将是一个编译错误。这是继承、方法覆盖、隐藏和声明的一般规则,不仅适用于两个继承的接口方法之间可能发生的冲突,还适用于接口和超类方法之间的冲突,甚至只是由于泛型的类型擦除引起的冲突.

JLS里这么说

类中的单个方法声明允许实现多个超接口的方法。

于 2013-03-25T06:30:50.357 回答
1

您正在扩展ActionCharacter,这意味着您希望ActionCharacter继承到您的Hero类的所有操作和属性。

这也包括fight操作。您标记Hero为正在实施CanFight,但您从ActionCharacter.

于 2013-03-25T06:18:26.073 回答
0

接口只声明一个方法,你不能在接口中定义一个方法。所以这意味着你给出一个你想要在接口中实现的草稿。

现在,您的 Hero 类继承了具有 public void Fight() 定义的 ActionCharacter 类。但是,这个fight() 与CanFight 的fight() 没有任何关系。所以如果你在 Hero 中定义了一个fight(),你将覆盖 ActionCharacter 的fight()。

由于您还实现了接口 CanFight,jvm 将允许这样做,因为您已在 CanFight 中声明了该方法,但它将被视为对 ActionCharacter 的fight() 的覆盖。

于 2013-03-25T06:27:23.250 回答
0

Hero 需要实现void figth();,但它继承void figth();自 ActionCharacter,因此满足要求。

于 2013-03-25T06:24:35.303 回答