一、静态分派:指JVM在方法重载时如何找到正确方法的过程
二、重载方法
public class StaticPatch {
public void sayHello(Human human) {
System.out.println("hello,Human");
}
public void sayHello(Man man) {
System.out.println("hello,man");
}
public void sayHello(Women women) {
System.out.println("hello,women");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
StaticPatch staticPatch = new StaticPatch();
Human man = new Man();
Human women = new Women();
staticPatch.sayHello(man);
staticPatch.sayHello(women);
}
}
代码输出的结果为:
hello,Human
hello,Human
以上代码是方法重载的样例,变量man和women的静态类型都是Human,但实际类型是具体但实现类,Man和Women。
在方法调用者明确的情况下,调用哪个方法则由他的参数类型和个数决定。
虚拟机在重载时是根据参数的静态类型而不是实际类型作为判断,并且静态类型是在编译器可知的,因此Javac编译器选择了sayHello(Human human)这个作为重载的方法。
如果把参数用强制转换修饰,那编译器在编译阶段则无法获取重载的方法,在运行期才确定调用具体的方法
man = new Women();
staticPatch.sayHello((Women)man); // hello women
staticPatch.sayHello((Man)man); // classCastException
三、重载方法的适配优先级
重载的版本并不是唯一的,而是一个比较合适的选择。
// public void sayHello(char pChar) {
// System.out.println("char");
// }
//
// public void sayHello(int pInt) {
// System.out.println("int");
// }
// public void sayHello(long pLong) {
// System.out.println("long");
// }
//
// public void sayHello(float pFloat) {
// System.out.println("float");
// }
// public void sayHello(double pDouble) {
// System.out.println("double");
// }
//
// public void sayHello(Character character) {
// System.out.println("character");
// }
public void sayHello(Serializable serializable) {
System.out.println("serializable");
}
以上的代码中,如果在Main方法传入'a'的参数调用
staticPatch.sayHello('a'); // char // int // long // float // double // character // serializable
重载时优先匹配到char的参数方法,如果没有char作为参数的方法,则将'a'转化为int类型来重载,找到int
如果int的参数方法也不存在,则转化为long来查找以此类推
优先的顺序为:
// char // int // long // float // double // Character // serializable
'a'不会转化为byte和short重载
四、动态分派
相较于静态分派,动态分派是多态性的一个表现。是指根据实际类型来选择具体的方法的过程。具体可对应到重写时,调用方法的寻找过程。
public abstract class Human {
public void sayHello() {
System.out.println("hello,Human");
}
}
public class Man extends Human{
@Override
public void sayHello() {
System.out.println("hello,Man");
}
}
public class Women extends Human{
@Override
public void sayHello() {
System.out.println("hello,Women");
}
}
以上代码演示了面向对象继承的样例。
在执行过程中,如果有以下代码:
Human man = new Man();
Human women = new Women();
man.sayHello();
women.sayHello();
输出结果为:
hello,Man
hello,Women
虚拟机在执行时,方法的调用者必须使用实际类型来作为判断依据,最终确定调用的方法。
man的静态类型为Human,但实际类型为Man,因此虚拟机在运行期调用的是Man的方法。