Question
package demo;
/**
* Created by zwj on 2016/3/26.
*/
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 ABCD {
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)); // 1:a a
System.out.println(a1.show(c)); //2:a a
System.out.println(a1.show(d)); //3:a d
System.out.println(a2.show(b)); //4:b a
System.out.println(a2.show(c)); //5:b a
System.out.println(a2.show(d)); //6:a d、
System.out.println(b.show(b));//7:b b
System.out.println(b.show(c)); //8:b b
System.out.println(b.show(d)); //9:a d
}
}
分析
首先我们要明白一个道理,对于java中的多态是编译看左边,运行看右边,方法在调用的时候会出现两种情况,一种是重载,另一种是子类重写。
重载
对重载来说,java在编译时候由编译器已经确定要调用的方法,也就是说编译器根据两个属性来做处理,首先是调用者,还有就是方法参数,通过这两个宗量就可以确定重载调用的方法,方法参数看传入的变量的静态类型,也就是声明类型,不是看其实际类型。
重写
对重写来说,java编译时候首先编译器会根据调用关系,编译生成相对字节码文件,然后根据创建对象的实际类型去调用相对应的子类或者父类的方法。
- 第一条语句,A类没有子类,执行第一条语句时候会去A中适应查找所以 输出为 A and A
- 跟第一条一样。
- 当调用show(D) 时候,由于A类中有声明显示D的方法,所以直接调用相对的方法,而不会根据前两条一样去适应。也就是方法参数的所对应方法的选择主要看静态类型,也就是传入参数的声明类型。
- 第四条语句,首先我们查左边,发现a2是A类型,所以会去A方法中查找,这时候我们找到适应的方法,也就是show(A obj) 但运行时候我们发现a2是 B类型所以会调用B中的相对应重写的方法,所以输出为 B and A
- 原理同第四条。
- 由于B中没有重写 show(D obj)方法所以会调用A中的方法做处理,因此会输出 A and D
- 直接调用自己方法
- 显而易见
- 跟前面分析一样
概括的说重载主要看传入参数的左边类型,重写调用时候如果存在重载,则首先根据左边类型看参数调用对应方法,然后再根据调用者的实际类型处理。