JVM - 方法静态分派和动态分派

一、静态分派:指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的方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值