java中静态和动态_java中的静态分派和动态分派

多态是java的基本特征之一,多态即一个对象具有多种形态(多种表达形式,猴子是动物的一种的表现形式),例如:子类是父类的一种形态。

当方法重载时,就会涉及到多态。

1:在重载时是通过参数的静态类型,而不是实际类型确定的, 静态类型是编译期确定的。

例如:

packagecom.li.chapter08;/*** 静态分派*/

public classStaticDispatch {static abstract classHuman{}static class Women extendsHuman{

}static class man extendsHuman{}public voidsayHello(Human human) {

System.out.println("hello,human");

}public voidsayHello(Women women) {

System.out.println("hello, women");

}public voidsayHello(man man) {

System.out.println("hello, man");

}public static voidmain(String[] args){

man man=newman(); //man是Human的一种形态,

Human women=newWomen(); //Human是静态类型,Women是实际类型

StaticDispatch staticDispatch=newStaticDispatch();

staticDispatch.sayHello(man); //编译期确定参数的类型,使用 human的静态类型Human

staticDispatch.sayHello(women);/*** 结果

* hello,man

hello,human*/}

}

其中:Human 被称为静态类型,man,Women被称为实际类型。在编译期,参数就确定了,使用对象的静态类型。

2:当重载方法时,参数可能有很多版本,也就是参数对象具有层次结构。具体选择哪一种重置方法要看静态类型的匹配优先级

例如;

packagecom.li.chapter08;importorg.junit.Test;/*** @program: GradleTestUseSubModule

*@author: Yafei Li

* @create: 2018-07-07 08:29

* 自定义方法重载,选择合适的重载方法

* 静态分派(Static Dispatch)发生在编译时期,分派根据静态类型(父类型)信息发生。静态分派对于我们来说并不陌生,方法重载就是静态分派。

* 动态单分派在Java语言中是在子类重写父类的方法时发生的

**/

public classMyStaticDispatcher {classOneGeneration{

}class TwoGeneration extendsOneGeneration{

}class ThreeGeneration extendsTwoGeneration{

}class FourGeneration extendsThreeGeneration{

}public voidtest(TwoGeneration twoGeneration) {

System.out.println("twoGenration");

}public voidtest(ThreeGeneration threeGeneration) {

System.out.println("threeGeneration");

}

@Testpublic voidmain(){

MyStaticDispatcher myStaticDispatcher=newMyStaticDispatcher();

FourGeneration fourGeneration=newFourGeneration();

myStaticDispatcher.test(fourGeneration);//打印:threeGeneration

}

}

当传入参数的对象,确定使用哪一种重载的方法时,需要根据参数对象在继承结构中从低到高遍历,选择第一个匹配的重载方法。

3:动态分派

动态分派是多态性的另一个重要体现——(重写)override

packagecom.li.chapter08;importorg.apache.tools.ant.taskdefs.Java;importjava.lang.invoke.MethodType;/*** 动态分派*/

public classDynamicDispatch {static abstract classHuman{protected abstract voidsayHello();

}static class Man extendsHuman{

@Override //重写protected voidsayHello() {

System.out.println("man say hello");

}

}static class Woman extendsHuman{

@Override//重写,覆盖

protected voidsayHello() {

System.out.println("Woman say hello");

}

}public static voidmain(String[] args){

Human man=newMan();

Human woman=newWoman();

man.sayHello();

woman.sayHello();

man=newWoman();

man.sayHello();/*** man say hello

Woman say hello

Woman say hello*/}

}

使用 invokevirtual指令进行多态性的查找时,使用以下几个步骤:

1)找到操作数栈顶的第一个元素所指向的对象的实际类型,记作C。

2)如果在类型C中找到与常量中的描述符和简单名称都相符的方法,则进行访问权限校验,如果通过则返回这个方法的直接引用,查找过程结束;如果不通过,则返回java.lang.IllegalAccessError异常。

3)否则,按照继承关系从下往上依次对C的各个父类进行第2步的搜索和验证过程。

4)如果始终没有找到合适的方法,则抛出java.lang.AbstractMethodError异常。

我们把这种在运行期根据实际类型确定方法执行版本的分派过程称为动态分派。

4:单分派与多分派

方法的接受者(所有者)与方法的参数统称为方法的宗量,根据分配基于多少宗量,可以划分为单分派和多分派两种。

单分派是根据一个宗量对目标方法进行选择,多分派则是根据多于一个宗量对目标方法进行选择。

java语言是动态单分派(只根据方法的接收者的实际类型确定),静态多分派(根据编译期静态类型和参数类型确定)语言。

5:访问者模式中用的动态多分派。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值