如果想要在同一个类中定义名字相同的方法,他们的参数类型必须不同,这些方法之间的关系,称之为重载。
选取的步骤:
- 在不考虑对基本类型自动装拆箱,以及可变长参数的情况下选择重载方法。
- 如果第一个阶段中没有找到适配的方法,那么在允许自动装拆箱,但不允许可变参数的情况下选取重载方法。
- 如果在第二阶段中没有找到相应的适配方法,那么允许自动装拆箱以及可变长参数的情况下选择重载方法。
如果子类定义了与父类中非私有方法同名的方法,而且两个方法的参数类型不同, 那么在子类中,这两个方法同样构成了重载。
如果两个方法都是静态的,那么子类中的方法隐藏了弗雷中的方法。如果两个方法都不是静态的,且都不是私有的,那么子类的方法重写了父类中方法。
JVM的静态绑定与动态绑定
Java虚拟机识别方法的关键在于类名、方法名以及方法描述符。
Java虚拟机与Java语言不同,它并不限制名字与桉树类型相同,但是返回类型不同的方法出现在同一个类中,对于调用这些方法的字节码来说,由于字节码所附带的方法描述包含了返回类型,
因此Java虚拟机能够准确地识别目标方法。
Java虚拟机中的静态绑定是指在解析时更能够直接识别目标方法的情况,动态绑定则指的是需要在运行过程中根据调用者的动态类型来识别目标方法的情况。
Java字节码中与调用相关的指令有5种:
- invokestatic:用于调用静态方法。
- invokespecial:用于调用私有实力方法,构造器,以及使用super关键字调用父类的实例方法或构造器,和实现接口的默认方法。
- invokevirtual:用于调用非私有实例方法。
- invokeinterface:用于调用接口方法.
- invokedynamic:用于动态方法。
唯一例外的在于,如果虚拟机能够确定目标方法有且仅有一个,,那么它可以不通过动态类型,直接确定目标方法。
调用指令的符号引用
invokevirtual和invokeinterface指令,都属于java虚拟机中的虚方法调用。
如果有的目标放啊被标记为final,那么Java虚拟机采用静态绑定。
Java虚拟机中,静态绑定包括用于调用静态方法的invokestatic指令,和用于调用构造器、私有实例方法以及超类非私有实例方法的invokespecial指令。
Java虚拟机实现动态绑定的关键是使用虚方法表、接口方法表。方法表本质是一个数组,每个数组元素指向一个当前类机器祖先类中非私有的实例方法。
方法表必须满足两个特质:子类方法表中包含子类方法表中的所有方法;子类方法在方法表中的索引值,与它所重写的父类方法的索引值相同。
对于静态方法调用而言,实际引用是将指向具体的目标方法,对于动态绑定的方法调用而言,实际引用则是方法表的索引值。
即时编译有两种性能更好的优化方法:内联缓存和方法内联。
内联缓存是一种加快动态绑定的优化技术,它能够缓存虚方法调用中调用者的动态类型,以及该类型所对应的目标方法。在之后的执行过程中,
如果碰到已经缓存的类型,内联缓存便会直接调用该类型所对应的目标方法。如果没有找到,从方法表中查找。
动态优化的方法:
- 单态指的是仅有一种状态的情况。
- 多态指的是有限数量种状态的情况。
- 超多态:更多中状态的情况。
单态内联缓存便只缓存一种动态类型以及它所对应的目标方法,比较所缓存的动态类型,如果命中,直接调用对应的目标方法。
多态内联缓存则缓存了多个动态类型以及目标方法。逐个将所缓存的动态类型与当前类型进行比较,如果命中,直接调用对应的目标方法。
网友评论