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();
}