小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Java運行期間動態(tài)確定調(diào)用方法的本質(zhì)

 臭小子的共享 2015-04-06

Java為什么能運行期間動態(tài)確定調(diào)用方法?是怎么實現(xiàn)的呢。

在繼承關(guān)系中,運行時動態(tài)確定要調(diào)用的方法的版本,是根據(jù)字節(jié)碼指令invokevirtual來完成的。需要從這個指令的"多態(tài)查找"過程說起。

invokevirtual的運行過程如下:

第一、找到操作數(shù)棧頂元素的實際類型,記做C,

第二、如果在才、C中找到與常量中描述符和簡單名稱都相同的方法,則進行權(quán)限校驗,如果通過,則返回這個方法的直接引用,查找過程結(jié)束。權(quán)限校驗不通過則返回java的illegalaccesserror。

第三、如果經(jīng)過第二步?jīng)]找到也沒拋出異常,則按照繼承關(guān)系在父類中查找。

第四、如果始終沒有找到,則跑出abstractmethoderror。

由于invokevirtual指令在執(zhí)行的第一步就是確定接收者的實際類型,所以調(diào)用的時候,針對不同的調(diào)用者(即所說的方法接收者)會把常量池中的類方法解析到不同的直接引用上,這個過程就是java語言“覆蓋”父類方法的本質(zhì),也就是“重寫”的本質(zhì)。

  1. 父類 a=new 子類1  
  2. 父類 b=new 子類2  
  3. a.test();  
  4. b.test();  

上面代碼a和b分別會調(diào)用兩個子類的test函數(shù),可以作為例子參考。

-------------------------------------------------------------------------------------------------------

上面的全部都是在說子類重寫父類的方法,那么如果在同一個類中重載一個函數(shù),那么是怎么確定調(diào)用版本的呢?

這需要從“靜態(tài)類型”和“動態(tài)類型”說起。

比如:

父類 a=new 子類,

在上面,父類是靜態(tài)類型,子類是動態(tài)類型,【因為子類是這個對象的實際類型,稱之為動態(tài)類型】

如果在一個類

  1. class TR {  
  2.     void test(父類 a) {  
  3.         System.out.print("father");  
  4.     }  
  5.   
  6.     void test(子類1 a) {  
  7.         System.out.print("child 1");  
  8.     }  
  9.   
  10.     void test(子類2 a) {  
  11.         System.out.print("child 2");  
  12.     }  
  13. }  

代碼如上。調(diào)用的時候,如果這么調(diào)用:

父類 a=new 父類

父類 b=new 子類1

父類 c=new 子類2

new TR().test(a);

new TR().test(b);

new TR().test(c);

那么這三句話會分別輸出什么呢?

這個有可能會有人回答錯誤。

會輸出三個father!

這是因為,虛擬機(準(zhǔn)確的說是編譯器)在重載時候是通過靜態(tài)類型而不是動態(tài)類型來確定調(diào)用方法的版本的。所以三個調(diào)用語句都會選擇void test(父類 a)作為調(diào)用函數(shù)。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多