java之动态分配和静态分配

本文通过两个示例详细解析了Java中的静态分派与动态分派机制,包括方法重载和重写的区别,并展示了字节码层面的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里先引用周志明书上对一个例子

public class StaticDispacher{
	static abstract class Human{

	
} 
static class Man extends Human{

	
}
static class Woman extends Human{


}
public void sayHello(Human guy){
System.out.println("hello guy");
}
public void sayHello(Man  man){
System.out.println("hello man");
}
public void sayHello(Woman woman){
System.out.println("hello woman");
}
public static void main(String[] args){
Human man = new Man();
Human woman = new Woman();
StaticDispacher sr = new StaticDispacher();
sr.sayHello(man);
sr.sayHello(woman);
}

}

程序运行结果 为 hello guy

                           hello guy

我们看下字节码 信息:

     26: invokevirtual #13                 // Method sayHello:(LStaticDispacher$Human;)V
        29: aload_3
        30: aload_2
        31: invokevirtual #13                 // Method sayHello:(LStaticDispacher$Human;)V

可以看到,在编译生成class后,在mian中调用对两个sayHello方法对参数都是Human。

静态分配发生在编译时期,对应于java的重载,即java中方法重载时,决定调用哪一个是根据编译时期d静态类型对而不是运行时类型。

动态分配:和重写Override有着密切的关系,看一下例子

public class DynamicDispatch{
	static abstract class Human{
	protected abstract void sayHello();	
	}
	static class Man extends Human{
	@Override
	protected void sayHello(){
	System.out.println("hello man");
	}
}
static class Woman extends Human{
	@Override
	protected void sayHello(){
	System.out.println("hello woman");
	}
}
public static void main(String[] args){
	Human man = new Man();
	Human woman = new Woman();
	man.sayHello();

	woman.sayHello();
	man = new Woman();
	man.sayHello();
	
}
}

方法的输出就不说了,我们看下字节码:

     16: aload_1
        17: invokevirtual #6                  // Method DynamicDispatch$Human.sayHello:()V
        20: aload_2
        21: invokevirtual #6                  // Method DynamicDispatch$Human.sayHello:()V
        24: new           #4                  // class DynamicDispatch$Woman
        27: dup
        28: invokespecial #5                  // Method DynamicDispatch$Woman."<init>":()V
        31: astore_1
        32: aload_1
        33: invokevirtual #6                  // Method DynamicDispatch$Human.sayHello:()V
        36: return

和上次一行,还是invokevirtual指令,但是这里会产生不同的效果,这和invikevirtual指令的多态查找有关,简单的说就是对操作数栈顶的元素,会找到操作数栈顶的第一个元素的引用指向的对象的实际类型,若此引用指向的数据和常量池中内容相符合,则返回这个直接引用,否则按照继承关系从下往上依次寻找,这样就定位到了方法的实际执行者。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值