有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么动态分派的目标不在编译时确定?

我现在正在读一本Java书籍,思考动态方法分派是如何工作的,已经有一段时间了。我知道这是一个强大而有价值的功能,但我不理解它的主要原理。例如,我有一个类B,它继承自类a并重写了a的一些方法。所以,当我写一个程序时,我可以使用这些表达式

A a = new B();
a.someOverridenMethod();

我知道在这种情况下会调用方法的版本B,而不是A。但我不明白的是,为什么编译器不能确定调用方法的哪个版本(超类或某个子类)?我的意思是,明确声明变量a将包含对类型B的对象的引用。那么,为什么即使在代码中明确声明,也只能在运行时确定这一点呢


共 (2) 个答案

  1. # 1 楼答案

    一个更明确的例子可能是:

    A a = null;
    
    if (getUserInput() == 'B')
    {
      a = new B();
    }
    else
    {
      a = new C();
    }
    
    a.overridenMethod();
    

    编译器不能可能知道这里要调用哪个方法——它在运行时由用户决定

  2. # 2 楼答案

    你完全误解了运行时的事情

    这意味着class A可以保存它的任何子类的引用,这些子类将在运行时确定。它们可能是另一个语句,比如a =new C();A a = new B();之后的a =new C();,由于它们可以是许多这样的语句,因此据说该方法的版本将在运行时确定

    也就是说,a将持有B的引用,可能在其他某个时刻,它将持有C的引用,其中BC都是A的子类

    下面是一个例子:

     class A {
    
    void override()
    {
        System.out.println("Inside A");
    }
    
    }
    
     class B extends A
    {
         void override()
         {
            System.out.println("Inside B");
         }  
    
    }
    
     class C extends A
     {
         void override()
         {
             System.out.println("Inside C");
         }
     }
    
     class Main
     {
         public static void main(String args[])
         {
             A a =new A();
    
             a.override();
             a=new B();
    
             a.override();
    
             a=new C();
    
             a.override();
         }
     }
    

    输出:

    Inside A
    Inside B
    Inside C
    

    希望这能消除你的疑虑