我們來看上面part1部分:
Cat cat_ = new Cat();
cat_.eat();
cat_.sleep();
cat_.work();
結果:
吃魚
貓會睡懶覺。
動物可以幫助人類干活!
cat_.work(); 這處繼承了父類Animal的方法
,還是很好理解的
我們接著看part2:
Animal cat=new Cat();
cat.eat();
cat.work();
cat.sleep();//此處編譯會報錯。
Animal dog=new Dog();
dog.eat();//結果為:吃骨頭。此處調用子類的同名方法。
這塊就比較特殊了,我們一句句來看
Animal cat=new Cat();
像這種這個 父類引用指向子類對象
,這種現象叫做: "向上轉型" ,也被稱為 多態的引用 。
cat.sleep();
這句 編譯器會提示 編譯報錯。表明:當我們當子類的對象作為父類的引用使用時,只能訪問子類中和父類中都有的方法,而無法去訪問子類中特有的方法
值得注意的是:向上轉型是安全的。但是缺點是:一旦向上轉型,子類會丟失的子類的擴展方法
,其實就是 子類中原本特有的方法就不能再被調用了。所以cat.sleep()
這句會編譯報錯。
cat.eat();
這句的結果打印:吃魚。程序這塊調用我們Cat定義的方法。
cat.work()
;這句的結果打印:動物可以幫助人類干活!我們上面Cat類沒有定義work方法,但是卻使用了父類的方法,這是不是很神奇。其實此處調的是父類的同名方法
Animal dog=new Dog();dog.eat();
這句的結果打印為:吃骨頭。此處調用子類的同名方法。
由此我們可以知道當發生向上轉型,去調用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤;如果有,再去調用子類的同名方法。如果子類沒有同名方法,會再次去調父類中的該方法
向上轉型
我們現在知道了 向上轉型時會丟失子類的擴展方法,哎,但我們就是想找回來,這可咋辦?
向下轉型
可以幫助我們,找回曾經失去的
我們來看part3:
Cat cat_real = (Cat)cat; //注意 此處的cat 對應上面父類Animal,可不是子類
cat_real.sleep();
Cat cat = (Cat)cat; cat222.sleep();
這個向下轉型
非常像"強轉"。
打印的結果:貓會睡懶覺。此處又能調用了 子類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();
}
}
執行結果:
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)
做對了嘛,不對的話,復制代碼去idea中debug看看
我們先看第一部分
Dog dog = new Dog();
程序內部的執行順序:
- 先 初始化 父類Animal 的屬性 int weight=10
- 然后 調用父類Animal的構造方法,執行print()
- 實際調用子類Dog的print()方法,打印:
this Dog Print:0
,由于此時的子類屬性weight 并未初始化 - 初始化 子類Dog 的屬性 int weight=20
- 調用 子類Dog的構造方法,執行print()
- 實際調用當前類的print()方法,打印
this Dog Print:20
其中有幾處我們需要注意一下:實例化子類dog,程序會去默認優先實例化父類,即子類實例化時會隱式傳遞Dog的this調用父類構造器進行初始化工作
,這個和JVM的雙親委派機制有關,這里就不展開講了,先挖個坑,以后再來填
-
編譯器
+關注
關注
1文章
1642瀏覽量
49229 -
面向對象編程
+關注
關注
0文章
22瀏覽量
1833
發布評論請先 登錄
相關推薦
評論