题目:写出下面程序的输出:
class A {
public String show(D obj){
return ("A and D");
}
public String show(A obj){
return ("A and A");
}
}
class B extends A{
public String show(B obj){
return ("B and B");
}
public String show(A obj){
return ("B and A");
}
}
class C extends B{}
class D extends B{}
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println(a1.show(b));
System.out.println(a1.show(c));
System.out.println(a1.show(d));
System.out.println(a2.show(b));
System.out.println(a2.show(c));
System.out.println(a2.show(d));
System.out.println(b.show(b));
System.out.println(b.show(c));
System.out.println(b.show(d));
}
}
===================================分割线===============================
答案:
A and A
A and A
A and D
B and A
B and A
A and D
B and B
B and B
A and D
到这里,肯定有人和上面的答案对不上了,特别是第4、5个输出,为啥输出是这样的?
第4个输出:首先,定义是:A a2 = new B();这里定义的是一个A类,然后初始化的时候是初始化A的一个子类B,然后参数是传入一个B,所以很多人这里直接就认为执行的是B中的show(B obj),于是得到输出:B and B
这种理解是完全错误的,首先你定义的是一个A,所以在A中是完全找不到show(B obj)方法的。这里我们传入的是一个B为参数,B是继承于A,所以会执行A中的show(A obj),但是初始化的是一个A的子类B,B中也有一个show(A obj),所以这里会直接执行子类B中的show(A obj),得到输出:B and A
后面的第5个输出也是同理的。
关于继承,一点理解:
1、如果定义的是子类,而且初始化的也是这个子类,例如上面的 B b = new B();如果子类中有重写这个方法,那么执行此方法的时候,则优先执行子类的方法,如果子类没有重写这个方法,才会执行父类的方法。
2、如果定义的是父类,初始化的时候却是它的一个子类,例如上面的A a2 = new B();首先你执行的肯定必须是A中有的方法才行,然后会到B中找是否有重写这个方法,如果有重写,则执行的是子类的那个方法。
3、在方法中定义传入参数为父类,但是你却可以传入它的任意一个子类,传入子类参数等同于定义的父类。