由于动态方法调度,在使用超类引用创建对象并通过该对象调用子类中已被重写的方法时,子类中被重写的方法将被调用,而不是超类中的原始方法。如果被重写的方法在另一个子类中再次被重写,会发生什么情况?
例如,假设A是父类,B扩展A,C扩展B。假设在A中编写了一个方法void m1(),然后它在B中被重写,然后在C中再次被重写。现在,如果我们创建一个对象,如下所示-
A obj = new B();
obj.m1();
将调用哪个方法?B区的那个还是C区的那个?
您可以自己尝试,但答案非常简单:将调用B的方法。
class A {
public static void main(String a[]) {
A obj = new B();
obj.m();
}
void m() {
System.out.println("It's A");
}
}
class B extends A {
@Override
void m() {
System.out.println("It's B");
}
}
class C extends B {
@Override
void m() {
System.out.println("It's C");
}
}
执行此程序将打印它是B
。请注意,main
的位置无关紧要。
通过一些思考,应该清楚的是»C
的方法将被调用«不能成为答案;如果是,在添加另一个class C2 extends B
重写方法void m()
后将调用哪个方法?
通常,如果您有obj。m(参数)
并要确定将执行哪个m
,请使用以下步骤:
obj
(在本例中为B
)的运行时类型
m(参数类型)
让我们用这个简单的Java代码: 我试图找出这三个ate()方法的哪个版本将运行。现在,当我键入 结果是“普通动物一般地吃”,这是完全可以理解的。 当我输入时也会发生同样的事情: 结果是“吃干草的马”,这也是完全合乎逻辑的。 这就是我困惑的地方。当我输入: 我得到: 我期望编译器从动物类引用调用ate()方法,而不是马对象引用。 所以我的问题是,当我有一个泛型引用变量类型引用一个对象类型时(比如:
问题内容: 让我们看一下这个简单的Java代码: 我试图找出三个eat()方法的哪个版本。现在,当我键入 输出是“一般动物食用”,这是完全可以理解的。 当我键入以下内容时,会发生相同的事情: 输出是“吃干草的马”,这完全是合乎逻辑的。 这就是让我感到困惑的地方。当我键入: 我得到: 我希望编译器从Animal类引用而不是Horse对象引用中调用eat()方法。 所以我的问题是,当我有一个引用对象类
我在类A中创建了两个方法,并在类B中重写,如下所示。我有一些关于动态多态性和重写的问题。 重写和动态多态总是同时发生吗?
为什么输出是"静态A"?
问题内容: 用Java如何实现方法重写?在C ++中,我们有vtable的概念。.这是如何在Java内部实现的? 问题答案: 为了回答这个问题,特别是在虚拟机中如何实现覆盖,在Java虚拟机编程(Google图书链接)中有一篇文章。 VM将在所引用的类中寻找适当的方法定义,然后逐步处理继承栈。显然,在某些阶段将应用各种优化。 有关相关字节码指令的说明,请参见此处: invokevirtual会查看
问题内容: 有没有理由可以更改覆盖方法的访问修饰符?例如, 然后将package-private访问修饰符更改为, 我只是出于好奇而问这个问题。 问题答案: Java不允许您对access修饰符进行 更严格的限制 ,因为这会违反以下规则:子类实例应该可以代替超类实例使用。但是当涉及到 减少 访问限制时……好吧,也许超类是由另一个人编写的,他们没有想到您要使用其类的方式。 人们编写的程序以及编程时所