【问题标题】:weird behavior of Inheritance and polymorphism [Java]继承和多态的奇怪行为 [Java]
【发布时间】:2017-10-27 03:18:57
【问题描述】:

假设我在 Java 中有以下类:

class B {

  public void foo(B obj) {
      System.out.print("B1 ");
  }

  public void foo(C obj) {
      System.out.print("B2 ");
  }
}

public class C extends B {

  public void foo(B obj) {
      System.out.print("C1 ");
  }

  public void foo(C obj) {
      System.out.print("C2 ");
  }

  public static void main(String[] args) {
      B c = new C();
      B b = new B();

      b.foo(c); 
      c.foo(b); 
      c.foo(c); 

  }
}

为什么我会得到以下结果:

B1

C1

C1

我不明白这部分到底发生了什么:

c.foo(b); // 打印 C1

c.foo(c); // 打印 C1

【问题讨论】:

  • 您预计会发生什么?此外,请合理地格式化您的代码,以便其他人更容易阅读。
  • 因为java没有双重调度。它使用参数的编译时类型来决定调用哪个方法。
  • 多态性只出现在点之前。它不适用于方法参数。

标签: java


【解决方案1】:

Java 虚拟机 (JVM) 为每个变量中引用的对象调用适当的方法。它不调用由变量类型定义的方法。这就是运行时多态性。

B c = new C();  
c.foo(b); 
c.foo(c); 

在上述情况下,虽然变量类型是B,但它所引用的对象是对象类型C。因此C类方法被调用。

现在为什么打印 C1 是因为 Java 语言规范如下:

调用方法时(第 15.12 节),在编译时使用实际参数(以及任何显式类型参数)的数量和参数的编译时类型来确定将被调用的方法(§15.12.2)。如果要调用的方法是实例方法,则将在运行时使用动态方法查找(第 15.12.4 节)确定要调用的实际方法。

【讨论】:

    【解决方案2】:

    b 和 c 变量都是 TYPE B。这是因为您将它们声明为:

    **B** c = new C();
    **B** b = new B();
    

    当您传递c.foo(b)c.foo(c) 时,因为它们都是B 类类型,它们将打印“C1”

    实际上可以通过运行代码来检查变量的类型:

     if (c instanceof B) {
            System.out.println("c is of type B"); //this will print
        }
        else {
            System.out.println("c is of type B");
        }
    
    
     if (b instanceof B) {
            System.out.println("b is of type B"); //this will print
        }
        else {
            System.out.println("b is of type B");
        }
    

    【讨论】:

    • 感谢您的解释,但在此命令中 B c = new C();不是 B 型而是 C 的实例吗?换句话说,这两个命令之间有什么区别: B c = new C();和 B b = 新 B(); ?
    • @Kal 表达式的type 和对象的class 是两个不同的东西;并且变量的type通常不同于它所引用的对象的class。调用哪个版本的重载方法取决于参数的类型。是否调用覆盖方法(即在子类型中定义的方法)取决于调用它的对象的
    • @DawoodibnKareem 说得真好!
    【解决方案3】:

    这是调用运行时多态性。

    当你做超类引用并分配一个子类对象和调用方法时,它将调用覆盖子类中的方法而不是超类原始方法。

    引用变量 c 属于 B 类型,这就是它打印 C1 的原因

    c.foo(c); // 打印 C1

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-08
      • 2012-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多