类的加载次序与继承
原創轉載請注明出處:http://www.cnblogs.com/chaeyeon/p/6146169.html
如果:A extends B
1.若要加載類A,應先加載父類B。而只要加載一個類,靜態字段就會分配內存,靜態代碼塊就會執行。則先為父類B(Object)的靜態變量分配內存以及執行父類的靜態語句塊(執行先后順序按由書寫執行決定)。
2.然后再加載子類A,及為類A的靜態變量分配內存以及執行類A的靜態語句塊。(并且1、2步驟只會在類第一次加載的時候執行,即最多執行一次)
結論一:子類的加載,必須先加載其父類,類的加載伴隨著,靜態變量的內存分配,靜態語句的執行。
可以通過:Class.forname(A)加載類A。在父類的靜態代碼中輸出父類中的靜態變量,并在子類的靜態代碼塊中輸出子類的靜態字段來驗證1,2結論。
3.若需實例化類A,則在子類的構造方法執行之前,先調用其父類B的構造函數。并且在調用其父類B的構造函數前、在父類中會發生:
????????1.父類B中的非靜態變量分配內存以及執行父類中的非靜態語句塊.再調用父類B中的構造函數初始化初始化父類中的字段(因為父類中的字段要被子類繼承,而字段的初始化,要通過自己的構造函數完成)。
2.然后再給類A中的非靜態變量分配內存以及執行類A非靜態語句塊.最后調用A中的構造函數初始化。( 并且第次實例化子類對象的時候過程3都會發生)
結論二:實例化對象的時候需要調用構造方法,由于子類繼承父類的成員變量,所以實例化子類的時候,在子類的構造方法中一定要先調用了父類的構造方法(super()在子類的構造方法的第一行)來給子類中繼承自父類的字段初始化,然后再執行子類中的構造函數來初始化子類特有的字段,這個步驟,會在每次實例化子類對象的時候重復執行。注意:一個類構造方法每次被調用之前,一定會先執行一次該類中的實例語句塊。
5.對于靜態方法和非靜態方法都是被動調用,即系統不會自動調用執行,所以用戶沒有調用時都不執行,方法都存放在方法區中(靜態區)等待用戶的調用。只有用戶調用時才給方法中的局部變量分配內存。
注意:加載不意味著執行!!!
總結:
子類的加載必先加載父類。類的加載伴隨著靜態變量的分配與靜態語句塊的執行(這個過程只會類第一次被加載時執行 )
子類的實例化,伴隨著父類的實例化(先實例化父類,然后實例化子類),此時伴隨著成員變量和實例語句塊的執行(這個過程在每次實例化子類的時候都會發生)
繼承:
1.子類會繼承父類中所有的字段和方法(包括私有的字段和方法),但構造方法不能被繼承。
2.子類即使繼承了父類的私有字段,也不能直接訪問,只能間接訪問,或不能訪問(但是可以通過父類提供的公開的方法中來做到間接地訪問父類中私有的成員字段或方法,既然能被訪問,說明子類為父類的私有字段分配了空間,繼承了父類的私有字段,不然數據往那里存)
通過.net的調試器,可以清楚的驗證這一結論,既然子類中可以訪問父類的成員方法的成員變量那么可以理解為在子類對象中包含一個父類對象。
3.構造方法雖然不能被繼承,但是子類中的任何一個構造方法執行前都會執行父類的構造方法。目的同繼承為了減少代碼的重復因為可以通過在子類中調用父類的構造來初始化子類,而不用在子類中在寫一遍對父類中成員變量賦值的代碼(如果子類中不顯示地調用默認調用父類的無參構造,可以在父類中的無參構造中輸出一名話,然后在實現化一個子類來驗證)
4.子類可以通過方法的重寫,或字段的重名來覆蓋都父類中的方法或都字段。但是只要該字段或方法在父類中不是私有的,在子類中仍然可以通過”super.“字段名或方法名去訪問。
5.this表示的就是當前對象,誰調用就指代誰,this就是對象的引象,保證對象的地址,每一個對象都有this存在堆中,可以理解為Object o=new Object();new返回的就是堆中對象中的this(this保存對象的引用,它的含義等價引用)靜態代碼段中沒有this
6、super(或者base)都是指代當前子類對象中的父類型的特征。super指代子類從父類中繼承過來的字段或方法,用于區分子類中重寫父類的方法或者子類覆蓋父類的中的字段,就可以通過”super.“方法名或字段名來顯示的在子類中調用父類中的方法或字段,即使這些方法或字段被子類重寫或覆蓋。super不是引用,不保存內存地址,它只是存在于this中來指代子類從父類繼承過來的數據(即父類中的數據),和子類中特有的數據。this能存在的地方super就存在,super是this的組成部分。
驗證:
? 從這張圖看所謂的繼承應該很明了
?
轉載于:https://www.cnblogs.com/chaeyeon/p/6146169.html
總結
- 上一篇: 嵌入式Linux驱动学习之路(十五)按键
- 下一篇: 图书管理模块功能设计