代码:
public class X
{
public void methodA() //Base class method
{
System.out.println ("hello, I'm methodA of class X");
}
}
public class Y extends X
{
public void methodA() //Derived Class method
{
System.out.println ("hello, I'm methodA of class Y");
}
}
public class Z
{
public static void main (String args []) {
X obj1 = new X(); // Reference and object X
X obj2 = new Y(); // X reference but Y object
obj1.methodA();
obj2.methodA();
}
}
输出:
hello, I'm methodA of class X
hello, I'm methodA of class Y
调用对象类型的方法而不是引用类型。这两条线都不应该是这个吗?
hello, I'm methodA of class X
hello, I'm methodA of class X
答案 0 :(得分:1)
编译器选择与方法调用最匹配的方法签名(在具有相同名称的所有重载方法中,可用于调用该方法的变量的编译时类型)。
但是,实际执行的方法仅在运行时确定,具体取决于调用该方法的变量引用的实例的运行时类型。这就是覆盖方法的意思。'
您可能会混淆方法重载(在编译时完成)与方法重写(在运行时完成)。
答案 1 :(得分:1)
很明显。当您在子类中再次声明methodA()
时。超级methodA()
被超越。所以现在每当你调用methodA()
时,都会调用子类的methodA()
。
X obj1 = new Y();
Y obj2 = new Y();
obj1.methodA();
((X)obj2).methodA();
两者都会调用overriden方法。
在java中,无法调用被覆盖的方法。只有在覆盖函数时调用超类的方法才能做到的事情是:
public void methodA() { //Derived Class method
super.methodA();
// add other stuff if you want here
}
答案 2 :(得分:1)
Java使用早期绑定',即在编译期间将名称与方法相关联,以及“动态调度”,选择与对象最密切相关的方法实现。在运行时键入。 Java在绑定时使用引用类型,因为在编译期间可能不知道对象的类型。
X obj1 = new X(); // obj1 is bound to X and of type X
if (i == 0) {
obj1 = new Y(); // obj1 is still bound to X, but now of type Y
}
obj1.methodA();
// Due to early binding, a compiler error occurs if X doesn't contain methodA
// Due to dynamic dispatch, if it exists, the methodA of obj1's type will be used. Otherwise the closest superclass's methodA will be used.