当前位置: 首页 > 知识库问答 >
问题:

重载和重写方法中的多态性

狄兴邦
2023-03-14

让我们用这个简单的Java代码:

public class Animal {
  public void eat() {
    System.out.println("Generic Animal Eating Generically");
   }
}

public class Horse extends Animal {
  public void eat() {
    System.out.println("Horse eating hay ");
  }

  public void eat(String s) {
    System.out.println("Horse eating " + s);
  }
}

我试图找出这三个ate()方法的哪个版本将运行。现在,当我键入

Animal a = new Animal();
a.eat();

结果是“普通动物一般地吃”,这是完全可以理解的。

当我输入时也会发生同样的事情:

Horse h = new Horse();
h.eat();

结果是“吃干草的马”,这也是完全合乎逻辑的。

这就是我困惑的地方。当我输入:

Animal ah = new Horse();
ah.eat();

我得到:

Horse eating hay

我期望编译器从动物类引用调用ate()方法,而不是马对象引用。

所以我的问题是,当我有一个泛型引用变量类型引用一个对象类型时(比如:Animal horse=new horse()),我如何确定编译器将调用哪个方法;

共有3个答案

宇文念
2023-03-14

发生这种情况是因为方法重写。在方法重写中,引用类型无关紧要,重要的是对象类型Animal ah只是对对象的引用,实际对象的类型为Horse。因此,将调用的方法,而不是引用类型动物的方法。

能可人
2023-03-14

这在Java中称为动态绑定。explicite对象类型不用于引用类型。

无法使用单个方法调用重写的超级方法和重写方法,请参阅:如何调用超类的重写方法。您可以向马添加一个方法,将调用委托给动物,如:

public class Horse extends Animal {
    public void animalEat() {
        super.eat();
    }

    public void eat() {
        System.out.println("Horse eating hay ");
    }
}
澹台鸿光
2023-03-14

我希望编译器从Animal类引用而不是Horse对象引用调用eat()方法。

让我们先纠正一下这个说法。变量ah是类型Animal的引用,语句new Horse()创建类型Horse的实例,并将其分配给Animal引用。

现在术语已经很清楚了,这种行为是可以预期的,被称为运行类型多态性或动态方法调度。在编译时,ate()基于引用类型解析,引用类型是动物,但是在运行时,将被调用的方法基于实例类型是Ma

当我有一个引用对象类型的泛型引用变量类型时,如何确定编译器将调用哪个方法

您可以遵循以下简单步骤:

  1. 检查正在调用的方法<代码>啊。eat()正在调用方法eat
  2. 查看父类和子类中是否存在具有完全相同签名(返回类型协方差除外)的方法。(是否覆盖了方法?)
  3. 检查引用类型。在Animal ah=new Horse()中,参考类型是Animal,即父类
  4. 检查实例类型。在Animal ah=new Horse()中,实例类型是Horse,它是子类

如果上述所有条件都满足,您将看到运行类型多态性,并且将调用子类中的方法。在任何其他场景中,将根据引用类型解析要调用的方法。

理解子类从父类继承方法也是值得的。假设您从Horse类中删除了public void eat()方法,您不再过度使用eat()方法;然而,Horse中的public void eat(String s)方法仍然被认为会使继承自Animaleat方法负担过重。接下来,让我们在Animal中添加一个public void eat(String s)方法。通过这个添加,您现在在Animal中重载了eat方法,在Horse类中重载了它。无论您如何更改代码,上面提到的4个步骤都将帮助您决定调用哪个方法。

 类似资料:
  • 问题内容: 让我们看一下这个简单的Java代码: 我试图找出三个eat()方法的哪个版本。现在,当我键入 输出是“一般动物食用”,这是完全可以理解的。 当我键入以下内容时,会发生相同的事情: 输出是“吃干草的马”,这完全是合乎逻辑的。 这就是让我感到困惑的地方。当我键入: 我得到: 我希望编译器从Animal类引用而不是Horse对象引用中调用eat()方法。 所以我的问题是,当我有一个引用对象类

  • 我试图理解重载和重写静态和非静态方法是如何工作的。事实上,我试图理解这些方法如何能够和不能出现在父类和子类中。我想出了下面的规则: 我们不能重写静态方法,只能隐藏它们。通过隐藏,我们的意思是在编译时根据引用变量类型决定执行哪个方法,而不是重写(,在运行时根据实例类型选择哪个方法执行)。 例如,让,然后隐藏. 我们可以重写实例方法。 例如重写. 两个或多个具有相同签名的方法不能以静态或非静态组合形式

  • 本文向大家介绍java中重载,继承,重写和多态的区别,包括了java中重载,继承,重写和多态的区别的使用技巧和注意事项,需要的朋友参考一下 重载,继承,重写和多态的区别: 1)继承是子类获得父类的成员。 2)重写是继承后重新实现父类的方法。 3)重载是在一个类里一系列参数不同名字相同的方法。 4)多态则是为了避免在父类里大量重载引起代码臃肿且难于维护。 网上看到一个有趣的说法是:继承是子类使用父类

  • 我想知道: 为什么在Java中不能重写静态方法? 静态方法可以在Java中重载吗?

  • 问题内容: 这是我遇到的一个测试练习问题,希望您能帮助我理解概念 让Hawk成为Bird的子类。假设某个类有两个重载的方法void foo(Hawk h)和void foo(Bird b)。在声明Bird x = new Hawk()之后,将在调用foo(x)中执行哪个版本; 这是我到目前为止的代码,有人可以向我解释为什么foo(bird b)被执行吗? 问题答案: Java执行重载解析以选择方法

  • 问题内容: 就Java而言,当有人问: 什么是多态性? 将超载或重载是一个可以接受的答案? 我认为还有更多。 如果你有一个抽象基类,它定义了一个没有实现的方法,并且你在子类中定义了该方法,那该方法是否仍然覆盖? 我认为过载不是肯定的正确答案。 问题答案: 表达多态性的最清晰方法是通过抽象基类(或接口) 此类是抽象的,因为该方法不适用于人类。只有男性和女性子类别才可以定义。同样,人类是一个抽象的概念