class TestGet {
public void a() {
System.out.println("aaa");
}
public void b() {
a();
}
}
class TestGet2 extends TestGet {
public void a() {
System.out.println("bbb");
}
public static void main(String[] args) {
TestGet t = new TestGet2();
t.b();
}
}
面试官说打印: aaa
到底是打印bbb还是aaa,求解释
t.b(); 他调用了父类的b方法,再根据b方法调用父类自己的a方法
当然打印出来的是aaa
t instanceof TestGet2 为true
简单来讲(但不确切),当对象t在父类中找到a方法后,还会继续在子类中找是否存在方法覆盖。
如果覆盖,还是会调用子类方法。 打印bbb
t.b(); t 永远指向的是TestGet2()实例,不管其定义时是TestGet还是什么类型,当通过这个t调用方法时,方法的行为总是表现出他们实际类型的行为所以,这里最终的 打印出 bbbPS: 文思创新面试官也忒水了吧。
System.out.println("aaa");
} public static void b() {
a();
}
}public class TestGet2 extends TestGet { public static void a() { System.out.println("bbb");
} public static void main(String[] args) {
TestGet2 t = new TestGet2();
t.b();
}
假若类A的a()的定义前有virtual,则在调用a()的时候,虚指针会指向虚表,找到子类B的a方法,输出bbb.
子类重写了父类的member方法
int i=1;
public void printI() {
System.out.println("i="+i);
}
}
public class B extneds A{
int i=2;
public static void main(String[] args) {
A b=new B();
b.printI();
}
}
int i=1;
public void printI() {
System.out.println("i="+i);
}
}
public class B extneds A{
int i=2;
public static void main(String[] args) {
B b=new B();
b.printI();
}
}
兄台,你说的没错,但为什么会这样呢?你有没有一个比较详细的解释:)在lz的例子里,也是先调用没有被重写的父类方法b(),然后在该方法里调用到一个有被重写的方法a()。
所以最后选择了子类里的a()来执行而这例子看起来也差不多啊,i在子类里也被重写了,为什么jvm在选择打印i的时候会打印父类的i而不会打印出有被重写子类的i呢?
System.out.println("aaa");
} public static void b() {
a();
}
}public class TestGet2 extends TestGet { public static void a() { System.out.println("bbb");
} public static void main(String[] args) {
TestGet2 t1 = new TestGet2();
t1.b(); //子类引用类型调用
TestGet t2 = new TestGet2();
t2.b(); //父类引用类型调用
}
这段代码无论是父类引用类型还是子类引用类型调用b()方法,输出结果都是:aaa
This is how Java implements run-time polymorphism.
当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中被定义过的,也就是说被子类覆盖的方法。