2013-02-17 90 views
1

我有一些像这样的代码:为什么Java不会编译这段代码?

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方面有效!

这是为什么?

回答

9

由于obj类型是ExampleOne,编译器将搜索您在ExampleOne类上obj调用该方法,如果找不到,就会抛出一个错误。

why doesn't Java choose the ExampleOne instance instead of ExampleTwo?

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

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

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

你的方法是只在ExampleTwo定义,但不ExampleOne。这会导致编译错误。

+0

这是不正确的..在运行时**这将是'ExampleTwo' ..错误是因为编译器无法在编译时找到该方法 – Anirudha 2013-02-17 07:41:00

1

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

你应该ExampleOne如果你想在一个多态的方式

1

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

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

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

好,

背后的理念是,通过该Java contruct,你会调用ExampleOne的方法与ExampleTwo的版本。

表示只允许您调用引用变量类型的方法(在您的情况下,它是ExampleOne)。但是,调用的方法的版本将是基础对象类型(即ExampleTwo)。并且由多态性促进。

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