<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在程式執行時,進行方法呼叫是最普遍,最頻繁的操作
方法呼叫不等於方法執行:
Class檔案的編譯過程不包括傳統編譯中的連線步驟
Class檔案中的一切方法呼叫在Class檔案裡面儲存的都是符號參照,而不是方法在在實際執行時記憶體佈局中的入口地址,即之前的直接參照:
所有方法呼叫中的目標方法在Class檔案裡都是一個常數池的參照
在類的載入解析階段,會將其中的一部分符號參照轉化為直接參照:
方法在程式真正執行之前就有一個可確定的呼叫版本,並且這個方法的呼叫版本在執行期是不可改變的
也就是說,呼叫目標在程式程式碼中完成,編譯器進行編譯時就必須確定下來,這也叫做方法解析
在Java中符合 "編譯期可知,執行期不可變" 的方法有兩大類:
這兩種方法各自的特點決定這兩種方法都不可能通過繼承或者別的方式重寫版本,因此適合在類載入階段進行解析
非虛方法: 在類載入階段會把符號參照解析為該方法的直接參照
虛方法: 在類載入階段不會將符號參照解析為該方法的直接參照
除去以上的非虛方法,其它的方法均為虛方法
public class StaticDispatch { static abstract class Human { } static class Man extends Human { } static class Woman extends Human { } public static void sayHello(Human guy) { System.out.println("Hello, Guy!"); } public static void sayHello(Man guy) { System.out.println("Hello, Gentleman!"); } public static void sayHello(woman guy) { System.out.println("Hello, Lady!"); } public static void main(String[] args) { Human man = new Man(); Human women = new Woman(); sayHello(man); sayHello(woman); } }
Human man = new Human();
Human
為變數的靜態型別
Man
為變數的實際型別
靜態型別和實際型別在程式中都會放生變化:
靜態型別:
實際型別:
Human human = new Man(); sayHello(man); sayHello((Man)man); // 型別轉換,靜態型別變化,轉型後的靜態型別一定是Man man = new woman(); // 實際型別變化,實際型別是不確定的 sayHello(man); sayHello((Woman)man); // 型別轉換,靜態型別變化
編譯器在過載時是通過引數的靜態型別而不是實際型別作為判斷依據,靜態型別在編譯期間可以知道:
編譯階段,Javac編譯器會根據引數的靜態型別決定使用哪個過載版本
靜態分派:
靜態分派發生在編譯階段,因此確定靜態分派的的動作不是由虛擬機器器執行的,而是由編譯器完成的
由於字面量沒有顯示靜態型別,只能通過語言上的規則去理解和推斷
public class LiteralTest { public static void sayHello(char arg) { System.out.println("Hello, char!"); } public static void sayHello(int arg) { System.out.println("Hello, int!"); } public static void sayHello(long arg) { System.out.println("Hello, long!"); } public static void sayHello(Character arg) { System.out.println("Hello, Character!"); } public static void main(String[] arg) { sayHello('a'); } }
編譯器將過載方法從上向下依次註釋,得到不同的輸出
如果編譯器無法確定要自定轉型為哪種型別,會提示型別模糊,拒絕編譯
public class LiteralTest { public static void sayHello(String arg) { // 新增過載方法 System.out.println("Hello, String!"); } public static void sayHello(char arg) { System.out.println("Hello, char!"); } public static void sayHello(int arg) { System.out.println("Hello, int!"); } public static void sayHello(long arg) { System.out.println("Hello, long!"); } public static void sayHello(Character arg) { System.out.println("Hello, Character!"); } public static void main(String[] args) { Random r = new Random(); String s = "abc"; int i = 0; sayHello(r.nextInt() % 2 != 0 ? s : 1 ); // 編譯錯誤 sayHello(r.nextInt() % 2 != 0 ? 'a' : false); //編譯錯誤 } }
public class DynamicDispatch { static abstract class Human { protected abstract void sayHello(); } static class Man extends Human { @override protected void sayHello() { System.out.println("Man Say Hello!"); } } static class Woman extends Human { @override protected void sayHello() { System.out.println("Woman Say Hello!"); } } public static void main(String[] args) { Human man = new Man(); Human women = new Woman(); man.sayHello(); woman.sayHello(); man = new Woman(); man.sayHello(); } }
這裡不是根據靜態型別決定的
導致這個現象的額原因 :這兩個變數的實際型別不同
Java虛擬機器器是如何根據實際型別分派方法的執行版本的: 從invokevirtual指令的多型查詢過程開始 ,invokevirtual指令執行時解析過程大致分為以下幾個步驟:
invokevirtual指令執行的第一步就是在執行時期確定接收者的實際型別,所以兩次呼叫中的invokevirtual指令把常數池中的類方法符號參照解析到了不同的直接參照上
這種在執行時期根據實際型別確定方法執行版本的分派過程就叫做動態分派
虛擬機器器概念解析的模式就是靜態分派和動態分派,可以理解虛擬機器器在分派中 "會做什麼" 這個問題
虛擬機器器 "具體是如何做到的" 在各種虛擬機器器實現上會有差別:
虛方法表中存放著各個方法的實際入口地址:
具有相同簽名的方法,在父類別,子類的虛方法表中具有一樣的索引序號:
這樣當型別變換時,僅僅需要變更查詢的方法表,就可以從不同的虛方法表中按索引轉換出所需要的入口地址
方法表一般在類載入階段的連線階段進行初始化:
準備了類的變數初始值後,虛擬機器器會把該類的方法表也初始化完畢
以上就是Java方法呼叫解析靜態分派動態分派執行過程的詳細內容,更多關於Java靜態動態分派執行過程的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45