今天在看jdk源碼的時候针姿,看到LinkedHashMap類,繼承了HashMap厌衙,同時實現(xiàn)了Map接口距淫。代碼如下
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
由于HashMap也繼承了Map接口,這就發(fā)生了一個有趣的事情婶希¢畔荆看上去LinkedHashMap通過繼承父類的實現(xiàn),以及自己的直接實現(xiàn)喻杈,重復實現(xiàn)了Map接口彤枢。
我比較好奇,這樣寫有什么特殊的作用嗎筒饰?
從JVM的角度理解缴啡,當一個子類繼承了父類,或者實現(xiàn)了父接口時瓷们,我們可以把這個類的對象當做父類或者父接口的對象來訪問业栅,這樣就把其他屬性屏蔽了,只能訪問到引用類型的屬性和方法谬晕。實現(xiàn)這種功能的原理是式镐,在JVM堆中創(chuàng)建的對象中,包含了一個對象頭信息固蚤,在對象頭中娘汞,有一個類型指針,叫Klass Pointer(對象頭指針)夕玩,指向對象所屬類型的Class對象的實例你弦,在類型的Class實例中(后面稱之為類元信息)惊豺,記錄了該類型的父類,以及實現(xiàn)的所有接口禽作。而在父類的類元信息中尸昧,記錄了父類的父類,以及父類的所有實現(xiàn)的接口旷偿。以此類推烹俗,即可知道某個類繼承了哪些類,實現(xiàn)了哪些接口萍程。
當我們以某個父類型或者父接口為引用訪問某個對象時幢妄,先從對象頭中找到它的類元信息,再根據(jù)類元信息找它實現(xiàn)的所有接口以及父類茫负,如果沒有在到父類中去找蕉鸳,以此類推,遞歸查詢忍法,直到查完所有的父類和接口潮尝。
所以不管是子類直接實現(xiàn)接口,還是通過父類間接實現(xiàn)接口饿序,對于子類本身來說勉失,都擁有了該接口提供的能力,對于使用該類的程序員來說原探,功能都是一樣的乱凿。如果從字節(jié)碼的角度來看,這樣做的結果是踢匣,子類的類元信息和父類的類元信息中,在實現(xiàn)接口的列表中都擁有了該接口戈抄,如果不這樣寫离唬,則子類的類元信息中沒有該接口信息。
總結一下划鸽,這種寫法在功能上沒有多大影響输莺,也許能夠起到強調子類實現(xiàn)了某一接口的作用。但在類的元數(shù)據(jù)中有小小區(qū)別裸诽,子類的元數(shù)據(jù)顯式的記錄了該實現(xiàn)的接口嫂用。