为什么Java不能编译这段代码?

时间:2013-02-17 07:36:34

标签: java class abstract-class abstract

我有一些像这样的代码:

abstract class ExampleOne {
   int dataOne = 1000;

   abstract void display();
}

class ExampleTwo extends ExampleOne {
   int dataTwo;

   ExampleTwo(int varOne) {
      dataTwo = varOne;
   }

   public void disp() {
      System.out.println("Testing");
   }

   public void display() {
      System.out.println(dataOne);
   }
}

class Example {
   public static void main(String args[]) {
      ExampleOne obj = new ExampleTwo(20);
      obj.disp();
      obj.display();
   }
}

当我编译它时,我收到一个错误:

                obj.disp(); 
                     ^
  symbol:   method disp()
  location: variable obj of type ExampleOne

为什么会这样?

我正在将ExampleTwo的实例分配给ExampleOne,为什么Java不选择ExampleOne实例而不是ExampleTwo

同样的概念适用于dynamic polymorphism

为什么会这样?

5 个答案:

答案 0 :(得分:9)

由于obj的类型为ExampleOne,编译器将在obj类中的ExampleOne上搜索您调用的方法,如果找不到,则会抛出错误。

  

为什么Java不选择ExampleOne实例而不是ExampleTwo?

这是因为编译时检查是基于引用类型而不是实际对象类型完成的。然后,在运行时调用的实际方法是根据被引用的实际对象决定的。这就是我们所说的方法调用的 动态调度

您可以向disp()类添加一个抽象的ExampleOne方法,只是为了确保编译器对调用感到满意。

abstract class ExampleOne{ 
    int dataOne=1000; 
    abstract void display(); 
    abstract void disp();
} 

答案 1 :(得分:4)

您的方法仅在ExampleTwo中定义,但不在ExampleOne中定义。这会导致编译错误。

答案 2 :(得分:1)

您的对象类型为ExampleOne。即使您创建了ExampleTwo的实例,编译器已知的对象类型(即方法和成员)也是ExampleOne,但没有声明disp()。

如果您希望以多态方式使用它,则应在disp()中声明一个抽象方法ExampleOne

答案 3 :(得分:1)

基类对象只能访问自己的类Methods。但disp()不是它的方法。这就是你得到错误的原因。

为了避免错误,你可以这样做:

ExampleTwo obj=new ExampleTwo(20); 
                  obj.disp(); 
                  obj.display();

答案 4 :(得分:1)

那么,

背后的概念是,通过这个java contruct,您将使用ExampleTwo的版本调用ExampleOne的方法。

意味着,您只能调用引用变量类型的方法(在您的情况下,它是ExampleOne)。但是调用的方法版本将是底层对象类型(即ExampleTwo)。并且它由多态性促进。

值得一提的是,您可以将对象分配给其类型的任何引用变量或其任何超类,在层次结构中。