首頁 > 易卦

深入理解JAVA虛擬機器學習筆記26

作者:由 道IT 發表于 易卦日期:2022-08-03

向上轉型是自動轉型嗎

每天進步一點點!

這裡說的方法呼叫階段的任務並不是執行過程,而是確定方法執行時的入口地址。

深入理解JAVA虛擬機器學習筆記26

前面我們已經學習過,在Class檔案的常量池中,型別為CONSTANT_Methodref_info的,儲存的就是方法資訊,並最終指向方法的符號引用。

對於方法呼叫,首先要進行的就是解析,這個其實在前面我們已經有了一些涉及,虛擬機器提供了五條位元組碼指令,用於方法呼叫,我們再來回顧一下。

1。 invokestatic:呼叫靜態方法;

2。 invokespecial:呼叫例項構造方法,私有方法和父類方法;

3。 invokevirtual:呼叫虛方法(除去能夠直接解析為直接引用之外的方法,都是虛方法);

4。 invokeinterface:呼叫介面方法,在執行時再確定一個實現此介面的物件;

5。 invokedynamic:在執行時動態解析出呼叫點限定符所引用的方法之後,呼叫該方法;

深入理解JAVA虛擬機器學習筆記26

解析是一個純靜態的過程,與解析相對的還有一個既包含靜態過程又包含動態過程的的呼叫——分派。

分派又分為靜態分派,動態分派,單分派和多分派。

深入理解JAVA虛擬機器學習筆記26

1。 靜態分派:發生在編譯階段。

在這個階段存在的一個問題就是自動轉型:當呼叫一個方法的時候,如果傳入的引數與方法列表中不能完全匹配的時候,那麼程式會如何處理呢?

首先,按照char>int>long>flaot>double進行一次向上轉型(向上轉型是安全的,不會造成資料丟失),尋找最近的一種型別進行匹配。

如果沒有找到,會檢視是否存在該資料型別封裝型別(Character,Integer,Long,Float,Double)。

這裡有一點需要特別注意:可變長引數(methodA(String。。。 obj))的過載優先順序是最低的,筆者就曾經遇到過這個bug。

如下圖所示,當用一個固定引數過載了另一個可變長引數的方法的時候,把原方法覆蓋了,找了很長時間,關鍵是還不報錯,真的坑(一般主要出現在多個同事共同開發的時候)!

深入理解JAVA虛擬機器學習筆記26

並且有一些單個引數能自動轉型,在可變長方法中是不成立的,筆者懷疑,以後邊長方法會不會不建議使用呢?用物件傳參也很好啊!

2。 動態分派:其實這個筆者認為完全可以對應到動態繫結中的內容,主要執行的是invokevirtual指令,大致步驟如下:

2。1 找到運算元棧頂的第一個元素所指向的物件的實際型別,記作C。

2。2如果在型別C中找到與常量中的描述符和簡單名稱相符合的方法,然後進行訪問許可權驗證,如果驗證透過則返回這個方法的直接引用,查詢過程結束;如果驗證不透過,則丟擲java。lang。IllegalAccessError異常。

2。3 否則未找到,就按照繼承關係從下往上依次對型別C的各個父類進行第2步的搜尋和驗證過程。

2。4 如果始終沒有找到合適的方法,則跑出java。lang。AbstractMethodError異常。

3。 單分派:Java中的動態分派都屬於單分派。

當執行動態分派的時候,虛擬機器能夠根據目標方法的簽名確定唯一的方法。

4。 多分派:Java中的靜態分派屬於多分派。

喜歡文章或想一起學習的朋友可以關注我,給我點贊,我將會持續更新,有什麼疑問或文中有不當之處請給我留言,真誠地希望能與大家一起交流探討,學習進步!