java虚拟机中,将符号引用转换为调用方法的直接引用与方法绑定机制相关。
静态链接:
当一个字节码文件被装载到jvm内部时,如果被调用的目标方法在编译器可知,且运行期保持不变时。这种情况下将调用方法的符号引用转换为直接引用的过程称之为静态链接。
动态链接:
如果被调用的方法在编译期无法被确定下来,也就是说,只能够在程序运行期将调用方法的符号引用转换为直接引用,由于这种引用转换过程具备动态性,因此也就被称之为动态链接;
对应的方法绑定机制为:早期绑定和晚期绑定
早期绑定:
早期绑定就是指被调用的目标方法如果在编译期可知,且运行期保持不变时,即可将这个方法与所属的类型进行绑定,这样一来,由于明确了被调用的目标方法究竟是哪一个,因此也可以使用静态链接的方式将符号引用转换为直接引用
晚期绑定:
如果被调用的方法在编译期无法被确定下来,只能够在程序运行期根据实际的类型绑定相关的方法,这种绑定方式也被称之为晚期绑定
classAnimal{public voideat(){
System.out.println("动物进食");
}
}interfaceHuntable{voidhunt();
}class Dog extends Animal implementsHuntable{
@Overridepublic voideat() {
System.out.println("狗吃骨头");
}
@Overridepublic voidhunt() {
System.out.println("捕食耗子,多管闲事");
}
}class Cat extends Animal implementsHuntable{publicCat(){super();//表现为:早期绑定
}publicCat(String name){this();//表现为:早期绑定
}
@Overridepublic voideat() {super.eat();//表现为:早期绑定
System.out.println("猫吃鱼");
}
@Overridepublic voidhunt() {
System.out.println("捕食耗子,天经地义");
}
}public classAnimalTest {public voidshowAnimal(Animal animal){
animal.eat();//表现为:晚期绑定
}public voidshowHunt(Huntable h){
h.hunt();//表现为:晚期绑定
}
}
虚方法和非虚方法
非虚方法:
如果方法在编译期就确定了具体的调用版本,这个版本在运行时是不可变的,这样的方法叫做非虚方法;
包括:静态方法,私有方法,final方法,实例构造器,父类方法都是非虚方法,其他方法称虚方法
虚拟机中提供了一下几种方法调用指令:
普通调用指令:
1.invokestatic:调用静态方法,解析阶段确定唯一方法版本
2.invokespecila:调用方法,私有及父类方法,解析阶段确定唯一方法版本
3.invokevirtual:调用所有虚方法
4.invokeinterface:调用接口方法
动态调用指令:
5.invokedynimic:动态解析出需要调用的方法,然后执行
前四条指令固化在虚拟机内部,方法的调用执行不可认为干预,而invokedynamic指令则支持由用户确定方法版本.其中invokestatic指令和invokespecial指令调用的方法称为非虚方法,其余的(final修饰的方法除外)称为虚方法.
classFather {publicFather() {
System.out.println("father的构造器");
}public static voidshowStatic(String str) {
System.out.println("father " +str);
}public final voidshowFinal() {
System.out.println("father show final");
}public voidshowCommon() {
System.out.println("father 普通方法");
}
}public class Son extendsFather {publicSon() {//invokespecial
super();
}public Son(intage) {//invokespecial
this();
}//不是重写的父类的静态方法,因为静态方法不能被重写!
public static voidshowStatic(String str) {
System.out.println("son " +str);
}private voidshowPrivate(String str) {
System.out.println("son private" +str);
}public voidshow() {//invokestatic
showStatic("atguigu.com");//invokestatic
super.showStatic("good!");//invokespecial
showPrivate("hello!");//invokespecial
super.showCommon();//invokevirtual
showFinal();//因为此方法声明有final,不能被子类重写,所以也认为此方法是非虚方法。//虚方法如下://invokevirtual
showCommon();
info();
MethodInterface in= null;//invokeinterface
in.methodA();
}public voidinfo(){
}public voiddisplay(Father f){
f.showCommon();
}public static voidmain(String[] args) {
Son so= newSon();
so.show();
}
}interfaceMethodInterface{voidmethodA();
}