我們來看上面part1部分:
Cat cat_ = new Cat();
cat_.eat();
cat_.sleep();
cat_.work();
結(jié)果:
吃魚
貓會睡懶覺。
動物可以幫助人類干活!
cat_.work(); 這處繼承了父類Animal的方法
,還是很好理解的
我們接著看part2:
Animal cat=new Cat();
cat.eat();
cat.work();
cat.sleep();//此處編譯會報錯。
Animal dog=new Dog();
dog.eat();//結(jié)果為:吃骨頭。此處調(diào)用子類的同名方法。
這塊就比較特殊了,我們一句句來看
Animal cat=new Cat();
像這種這個 父類引用指向子類對象
,這種現(xiàn)象叫做: "向上轉(zhuǎn)型" ,也被稱為 多態(tài)的引用 。
cat.sleep();
這句 編譯器會提示 編譯報錯。表明:當(dāng)我們當(dāng)子類的對象作為父類的引用使用時,只能訪問子類中和父類中都有的方法,而無法去訪問子類中特有的方法
值得注意的是:向上轉(zhuǎn)型是安全的。但是缺點是:一旦向上轉(zhuǎn)型,子類會丟失的子類的擴展方法
,其實就是 子類中原本特有的方法就不能再被調(diào)用了。所以cat.sleep()
這句會編譯報錯。
cat.eat();
這句的結(jié)果打?。撼贼~。程序這塊調(diào)用我們Cat定義的方法。
cat.work()
;這句的結(jié)果打?。簞游锟梢詭椭祟惛苫?!我們上面Cat類沒有定義work方法,但是卻使用了父類的方法,這是不是很神奇。其實此處調(diào)的是父類的同名方法
Animal dog=new Dog();dog.eat();
這句的結(jié)果打印為:吃骨頭。此處調(diào)用子類的同名方法。
由此我們可以知道當(dāng)發(fā)生向上轉(zhuǎn)型,去調(diào)用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤;如果有,再去調(diào)用子類的同名方法。如果子類沒有同名方法,會再次去調(diào)父類中的該方法
向上轉(zhuǎn)型
我們現(xiàn)在知道了 向上轉(zhuǎn)型時會丟失子類的擴展方法,哎,但我們就是想找回來,這可咋辦?
向下轉(zhuǎn)型
可以幫助我們,找回曾經(jīng)失去的
我們來看part3:
Cat cat_real = (Cat)cat; //注意 此處的cat 對應(yīng)上面父類Animal,可不是子類
cat_real.sleep();
Cat cat = (Cat)cat; cat222.sleep();
這個向下轉(zhuǎn)型
非常像"強轉(zhuǎn)"。
打印的結(jié)果:貓會睡懶覺。此處又能調(diào)用了 子類Cat 的 sleep()方法了。
一道簡單的面試題
我們再來看一道有意思的題,來強化理解
public class Main {
static class Animal{
int weight = 10;
public void print() {
System.out.println("this Animal Print:" + weight);
}
public Animal() {
print();
}
}
static class Dog extends Animal {
int weight = 20;
@Override
public void print() {
System.out.println("this Dog Print:" + weight);
}
public Dog() {
print();
}
}
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println("---------------");
Animal dog222 = new Dog();
Dog dog333 = (Dog)dog222;
System.out.println("---------------");
Dog dog444 = (Dog)new Animal();
}
}
執(zhí)行結(jié)果:
this Dog Print:0
this Dog Print:20
---------------
this Dog Print:0
this Dog Print:20
---------------
this Animal Print:10
Exception in thread "main" java.lang.ClassCastException: com.zj.Main$Animal cannot be cast to com.zj.Main$Dog
at com.zj.Main.main(Main.java:15)
做對了嘛,不對的話,復(fù)制代碼去idea中debug看看
我們先看第一部分
Dog dog = new Dog();
程序內(nèi)部的執(zhí)行順序:
- 先 初始化 父類Animal 的屬性 int weight=10
- 然后 調(diào)用父類Animal的構(gòu)造方法,執(zhí)行print()
- 實際調(diào)用子類Dog的print()方法,打?。?code>this Dog Print:0,由于此時的子類屬性weight 并未初始化
- 初始化 子類Dog 的屬性 int weight=20
- 調(diào)用 子類Dog的構(gòu)造方法,執(zhí)行print()
- 實際調(diào)用當(dāng)前類的print()方法,打印
this Dog Print:20
其中有幾處我們需要注意一下:實例化子類dog,程序會去默認優(yōu)先實例化父類,即子類實例化時會隱式傳遞Dog的this調(diào)用父類構(gòu)造器進行初始化工作
,這個和JVM的雙親委派機制有關(guān),這里就不展開講了,先挖個坑,以后再來填
-
編譯器
+關(guān)注
關(guān)注
1文章
1636瀏覽量
49172 -
面向?qū)ο缶幊?/span>
+關(guān)注
關(guān)注
0文章
22瀏覽量
1830
發(fā)布評論請先 登錄
相關(guān)推薦
評論