abstract class A1
{
public abstract void m1();
public void m2()
{
System.out.println("Green");
}
}
abstract class A2 extends A1
{
public void m1()
{
System.out.println("Cyan");
}
public void m2()
{
System.out.println("Blue");
}
public abstract void m3();
}
public class A3 extends A2{
public void m1()
{
System.out.println("Yellow");
}
public void m2()
{
System.out.println("Pink");
}
public void m3()
{
System.out.println("Red");
}
public static void main(String[] args)
{
System.out.println(" inside main ");
A2 tp = new A3();
tp.m1();
tp.m2();
tp.m3();
}
}
输出上述代码:
inside main
Yellow
Pink
Red
有人可以解释为什么它会打印黄色,粉红色和红色而不是青色绿色红色? 为什么代码不能用于代码执行的抽象类?
答案 0 :(得分:1)
这是因为你没有扩展方法而是Override
方法,如果你想要调用parent-methods,你需要在{{1}方法中自己调用它们}}
答案 1 :(得分:1)
因为与C ++不同,在Java中,所有实例方法都是虚拟的。
答案 2 :(得分:0)
这就是我解释它的方式。
编译器将首先检查方法调用是否为 legal 。为此,它检查调用该方法的引用变量的声明类型 (无论它所指的实际对象的类型如何)。 如果方法是在引用变量的声明类型(包括继承方法)中定义的,则方法调用将是合法的。 在您的示例中,引用变量tp的声明类型为A2 。方法m1,m2和m3在A2中定义。所以 tp.m1(); , tp.m2()和 tp.m3(); 是编译器的合法方法调用,无论 tp实际上是指A3对象。
然后在运行时, JVM将检查引用变量引用的实际对象并应用实际对象中的方法实现(如果有)。如果jvm在实际对象中没有找到该方法的任何实现,它将应用在引用变量的声明类型中找到的方法实现(包括继承的方法)。 在你的例子中,tp(甚至声明为A2类型),实际上指的是A3类型的对象(由于A3扩展了A2,这是合法的)。因此,当调用方法m1,m2和时,jvm将执行类A3中的实现。立方米。 如果你没有在A3类中重新定义(覆盖)方法m2,那么输出将是:
inside main
Yellow
Blue
Red
答案 3 :(得分:0)
这就是Override的含义。 A2中的A3 OVERRIDES m1方法中的m1方法。 如果从A3中删除m1方法,您将在输出中获得Cayan,而不是黄色。
同样,如果你从A3和A2中删除m2,你将在输出中获得绿色,而不是粉红色。