今天在看到了一道面試題,題目是一道代碼閱讀題,問下面的代碼輸出結果是什么?
我最開始的理解:
上面的代碼我們可以看到,上面的類中有兩個內部類Sub和Super,Sub繼承了Super,Sub類重寫了父類Super的getType方法,這是一個靜態方法;
而在main方法中創建了一個Super變量指向了一個子類Sub對象,並調用了其getType方法。按照多態的原理,這個變量調用的應該是子類的getType方法,也就是會得到三個字符串“Sub”,但是結果並非如此,結果如下:
這個結果是調用了三次父類Super的第一個getType方法產生的。
結論:
會產生這個結果的原因顯而易見,子類重寫了父類的靜態方法,但是並沒有將其覆蓋,二者之間仍然獨立,所以類型是父類Super的變量,調用的仍然是父類的靜態方法,而不是子類的重寫方法。也就是說子類並不能重寫父類的靜態方法。
解釋:
我上網查了一些別人的博客,理解了其中的原因。
首先要明確一個概念,靜態方法屬於類,在編譯階段類被加載時,類的靜態方法或者屬性就會被分配內存,存儲到類所在的內存中(堆內存的方法區中);而類的非靜態方法卻是屬於對象的,每個對象都有一份非靜態方法的引用,並且若方法被重寫,引用的就是子類重寫的方法,且這是在運行時創建;
正因如此,即使子類重寫了父類的靜態方法,但是本質上它們還是兩個獨立的類,在內存中分別占用不同的內存,它們的靜態方法也是在編譯時就被加載,獨立的占用着不同的內存。上面的代碼中,一個父類的變量,指向子類的對象,調用一個被子類重寫的靜態方法時,由於這是一個父類的變量,並且靜態方法屬於類,所以在調用時,JVM會去父類所在的內存中尋找這個方法,所以最終的結果就是調用父類的方法,而不是子類重寫的方法。