從對象的內(nèi)存角度來理解試試. 假設現(xiàn)在有一個父類Father,它里面的變量需要占用1M內(nèi)存.有一個它的子類Son,它里面的變量需要占用0.5M內(nèi)存. 現(xiàn)在通過代碼來看看內(nèi)存的分配情況: Father f = new Father();//系統(tǒng)將分配1M內(nèi)存. Son s = new Son();//系統(tǒng)將分配1.5M內(nèi)存!因為子類中有一個隱藏的引用super會指向父類實例,所以在實例化子類之前會先實例化一個父類,也就是說會先執(zhí)行父類的構造函數(shù).由于s中包含了父類的實例,所以s可以調(diào)用父類的方法. Son s1 = s;//s1指向那1.5M的內(nèi)存. Father f1 = (Father)s; 相當于Father f1 = new Son(); 為向上類型轉(zhuǎn)換,可省略,因為子類就是父類,如貓就是動物 //這時f1會指向那1.5M內(nèi)存中的1M內(nèi)存,即是說,f1只是指向了s中實例的父類實例對象,所以f1只能調(diào)用父類的方法(存儲在1M內(nèi)存中),而不能調(diào)用子類的方法(存儲在0.5M內(nèi)存中). Son s2 = (Son)f; //Error 不可直接向下類型轉(zhuǎn)換 //這句代碼運行時會報ClassCastException.因為f中只有1M內(nèi)存,而子類的引用都必須要有1.5M的內(nèi)存,所以無法轉(zhuǎn)換. Son s3 = (Son)f1; 強制類型轉(zhuǎn)換,為向下類型轉(zhuǎn)換,前提是父類引用要先指向子類對象 //這句可以通過運行,這時s3指向那1.5M的內(nèi)存.由于f1是由s轉(zhuǎn)換過來的,所以它是有1.5M的內(nèi)存的,只是它指向的只有1M內(nèi)存. 示例: 1 .如果你想實現(xiàn)多態(tài),那么必須有三個條件,父類引用,子類對象,方法覆蓋你這里如果Fathor類有一個show()方法,那么形成方法覆蓋,那么此時就可以這么寫:obj.show(),此刻形成了多態(tài). 2. 沒有方法覆蓋,那你這里只能解釋為父類引用去訪問一個子類的方法,當然,父類引用沒有這么大范圍的權限,當然會報錯 PS:多態(tài)實際上是一種機制,在編譯時刻,會生成一張?zhí)摂M表,來記錄所有覆蓋的方法,沒有被覆蓋的方法是不會記錄到這張表的.若一個父類引用調(diào)用了沒有覆蓋的子類方法,那么是不符合該表的,那么編譯時刻就會報錯. 在執(zhí)行程序的時候,虛擬機會去這張?zhí)摂M表中找覆蓋的方法,比如引用中實際上存的是一個子類對象引用,那么就會去找子類中的相應的覆蓋的方法來執(zhí)行
定義一個父類類型的引用指向一個子類的對象既可以使用子類強大的功能,又可以抽取父類的共性。
變量是不存在重寫覆蓋的!
類中的屬性是沒有多態(tài)性的,即你在引用上面使用屬性時,系統(tǒng)只會去找引用的靜態(tài)類型中的那個屬性,而與它的實際類型無關。 |
|