1. 程式人生 > >靜態分派與動態分派——記一次被騰訊面試官暴虐的面試經歷

靜態分派與動態分派——記一次被騰訊面試官暴虐的面試經歷

在騰訊的面試中被問到了過載的執行時多型是怎麼實現的,顯然這一塊是我的知識盲區,所以趕緊補充下。 ##靜態分派 依賴靜態型別來定位方法執行版本的分派動作稱作靜態分派,靜態分派的典型是方法過載。如下程式碼例項: ```java public class StaticDispatch { static abstract class Human { } static class Man extends Human { } static class Woman extends Human { } public void sayHello (Human guy) { System.out.println("hello,guy"); } public void sayHello (Man guy) { System.out.println("hello,gentleman"); } public void sayHello (Woman guy) { System.out.println("hello,lady"); } public static void main(String[] args) { Human man = new Man(); Human woman = new Woman(); StaticDispatch sr = new StaticDispatch(); sr.sayHello(man);//hello,guy! sr.sayHello(woman);//hello,guy! } } ``` 對於這段程式碼的執行結果想必大家都很清楚,究其原因,過載的方法呼叫是由靜態型別而非實際型別決定的,在編譯器便決定了使用哪個過載版本,並會把這個方法的符號引用寫到main()方法的兩條invokevirtual指令的引數中。 總結:Java過載是基於靜態分派完成的。 ##動態分派 我們知道Java多型性另一種實現方式是“重寫”,而這種執行時多型編譯器是不可能知道它的實際呼叫的例項的,如下程式碼所示: ```java Scanner in = new Scanner(System.in); Person person = null; if (in.nextLine().equals("chinese")) { person = new Chinese(); } else { person = new English(); } person.sayHello(); ``` 在過載的場景下,JVM使用的是動態分派,即在執行時確定接受者的實際型別。JVM會在運算元棧中找到指向物件的實際型別,之後在該類的方法表(存在方法區中,存放著各個方法的實際入口)中找到對應描述符和和簡單名稱都相符的方法,同時進行訪問許可權校驗,如通過則查詢過程結束。如果沒有找到匹配的方法,則通過繼承關係在該類的父類的方法表中查詢,查詢到則結束,否則拋異常。 ## 參考資料 [多型在 Java 和 C++ 程式語言中的實現比較](https://www.ibm.com/developerworks/cn/java/j-lo-polymorph/) 《深入理解Java虛