1

如果方法调用是动态绑定的,那么编译器为什么会抱怨

类型 B 的方法 run() 未定义

为什么编译器检查是否存在在类 b 中运行的方法

这是代码

import java.lang.*;

public class Program
{
    public static void main(String [] args) 
    { 
        B a = new A(); 
          a.run();//compiler complains at this line.
        a.p(10);  
        a.p(10.0); 
    } 
} 
    class B { 
        public void p(int i) 
        { 
            System.out.println(i*2); 
        } 
    }

    class A  extends B{ 
        public void p(int i) 
        { 
            System.out.println(i); 
        } 
        public void run(){

        }
    } 
4

3 回答 3

3

Java 设计为一种静态类型语言,这意味着编译器必须知道并能够保证该方法的实现存在于每个具体对象中。(Maxim Shoustin 的回答通过一个例子很好地展示了这个设计决策背后的原因。)

如果编译器在没有任何保证的情况下假设未知对象会碰巧具有特定方法,那么它将使 Java 成为鸭子类型语言。这可能有其自身的优势,但它不符合 Java 的设计目标。

实际上,在静态类型语言中,虚拟(意味着非最终)方法(例如您的run()方法)是动态解析的,但用于解析它们的策略仍然是在编译时编写的。例如,在多态性的许多实现中,该策略可能涉及读取 vTable(包含该对象的虚拟方法的实际实现地址的表)的正确偏移量——利用语言的类型安全性来获得一些动态调度期间的性能。

于 2013-09-14T20:14:43.607 回答
2

类型 B 的方法 run() 未定义

该错误是不言自明的。该类型B没有名为的方法.run()

B a = new A()意味着您的变量a是类型的B,这就是系统对变量的所有了解a

如果你做了Object s = new String()然后做s.toLowerCase()了它也会失败,因为变量s的类型Object不是 type String

无论您的变量是什么类型,都是您可以在该类型上调用的唯一行为。

于 2013-09-14T20:18:35.167 回答
2

它很容易显示:

让我稍微修改一下你的代码:

  • B = 动物
  • A = 牛

更换后:

public class Program
{
    public static void main(String [] args) 
    { 
        Animal a = new Cow(); 
          a.sayMooo();//compiler complains at this line. You try to animal to say "moo"?
          a.speed(10);  
          a.speed(10.0); 
    } 
} 
    class Animal { 
        public void speed(int i) 
        { 
            System.out.println(i*2); 
        } 
    }

    class Cow  extends Animal{ 
        public void p(int i) 
        { 
            System.out.println(i); 
        } 
        public void sayMooo(){

        }
    } 

不是所有的动物都是牛

并且确定

不是所有的动物都会说“mooo”

所有的牛都是动物

于 2013-09-14T20:19:47.793 回答