整理一个多态的题目:
代码如下:
package test;
public class Test {
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("1--" + a1.show(b));
System.out.println("2--" + a1.show(c));
System.out.println("3--" + a1.show(d));
System.out.println("4--" + a2.show(b));
System.out.println("5--" + a2.show(c));
System.out.println("6--" + a2.show(d));
System.out.println("7--" + b.show(b));
System.out.println("8--" + b.show(c));
System.out.println("9--" + b.show(d));
}
}
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{
}
运行结果:
1--A and A
2--A and A
3--A and D
4--B and A
5--B and A
6--A and D
7--B and B
8--B and B
9--A and D
网上经典题:
看了好多资料,最后觉得还是根据1 编译期静态分派 2 运行期动态分派 来解释,容易理解。
编译期和运行期间的工作是这样的:
编译期只检查参数的引用类型:说白了,就是方法的重载,这种行为也期称为编译期多态。
运行期间指定对象的类型,并且运行该对象的方法。就是方法的重写,这种行为称为运行期多态,就是我们平时说的多态。
我记得刚学java继承的时候,有这样的口头禅:
1.属性看引用,对象看方法:(父类的引用变量指向子类的对象)前半句调用属性,看的是引用变量;后半句,对象看方法,说的就是重写。
2.编译看左边,运行看右边:说的是编译期重载,运行期的重写
按照上边的逻辑,展开这几个输出的分析;
1,2,3比较容易理解,直接看第四个。
第四个输出语句:
System.out.println("1--" + a1.show(b));
编译期检查参数的引用类型:
1.参数b的类型是B,此时调用A中的show(B b),发现没有这个方法;2.但是B可以向上转型为A,调用A中的show(A b),发现有这个方法;
3.暂定调用A中show(A object)这个方法;
运行期间指定对象,并调用该对象的方法:
1.因为a2指向的是B类的对象,B中重写了show(A object)这个方法。输出就是
5--B and A
按照这个逻辑,一步一步的执行,下边所有的方法均可以得出正确结果。
看了几篇别的博客,提出的方式是:其实在继承链中对象方法的调用存在一个优先级:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。
这个逻辑,可以得出结果,不过不知道它这个怎么来的。昨天看了一晚上没搞明白,汗!
参考:http://blog.csdn.net/chenssy/article/details/12786385
参考:http://lib.csdn.net/article/javase/2208
参考:http://www.runoob.com/java/java-override-overload.html