为什么即使对象被上升,Java也会调用重写方法?

时间:2014-07-02 18:50:53

标签: java

我有以下课程:

public abstract class Animal
{
    private String species;
    public Animal(String ll)
    {
        species = ll;
    }

    public abstract void speak();

    public String toString()
    {
        return "Species: " + species;
    }

}  

第二课:

public class Raven extends Animal
{
    String name;
    public Raven(String emri)
    {
        super("Raven");
        name = emri;
    }

    public void speak()
    {
        System.out.println("krra krra");
    }

    public String toString()
    {
        return super.toString() + "\nName : "+ name ;
    }

}

和测试类:

public class TestAnimals
{
    public static void main(String args[])
    {
        Raven blabla = new Raven("Ziosh");
        Animal a = blabla;

        System.out.println(a.toString());
    }
}  

当我执行测试课时,我得到:

Species: Raven
Name: Ziosh

我不明白为什么Java会使用" new" toString()方法,即使我们" upcast" Raven对象是动物? 感谢。

4 个答案:

答案 0 :(得分:7)

因为那是多态性的全部内容:您可以在不知道对象的实际具体类型的情况下调用对象的方法,并且将调用在此具体类型中定义的适当方法。

这就像真实的物体一样:如果我给你一辆车,即使你不知道它实际上是一辆混合动力汽车,当你驾驶它时,汽车的行为就像一辆混合动力汽车。 / p>

在您的示例中,ablabla是对同一对象的两个引用,它是Raven实例。所以这个对象*说* s和* toString * s就像Raven。

答案 1 :(得分:3)

当你在java中调用一个方法时,即使它被强制转换为超类型,它总是会查找调用次数最多的方法。

来自http://docs.oracle.com/javase/tutorial/java/IandI/override.html

  

隐藏静态方法和覆盖实例方法之间的区别具有重要意义:

     
      
  • 被调用的重写实例方法的版本是子类中的版本。
  •   
  • 被调用的隐藏静态方法的版本取决于它是从超类还是从子类调用。
  •   

答案 2 :(得分:1)

Raven blabla = new Raven("Ziosh");
Animal a = blabla;

此处,ablabla引用完全相同的对象,您可以通过以下方式确认:

System.out.println(a == blabla);
// prints "true"

因此,a实际上是Raven,所以即使您将其标记为Raven,它也会像Animal一样说话。

从人的角度考虑另一种解释。让实现在子类的对象上执行实际上可能非常危险。想象一下Bicycle类,它更专业BicycleWithLittleWheels。关于后者的事情,小轮子是非常脆弱的,如果你试图骑得太快,它们可能会破裂。如果你让某人骑自行车就好像是一辆普通的自行车,完全明显的小轮子,他可能会打破它。按照类似的逻辑,你可能不应该像大锤那样使用高精度牙钻。

这就是为什么,直观地说,你不应该让一个专门的对象被视为更一般的形式。当然,在某些情况下,使用专门的对象可能是有意义的,就好像它是更通用的东西,但并非总是如此。编译器如何将安全案例与不安全案件区分开来?那太难了。因此,为了保持安全,语言不会让你这样做。

答案 3 :(得分:0)

Java总是使用该帖子中描述的实例方法: java override method invocation