public class 父類A { int age = 10; protected void say() { System.out.println("父類A"); } public 父類A() { override(); } public void override() { System.out.println("父類A override"); } } class 子類B extends 父類A { int age = 9; private final Date date; public 子類B() { date = new Date(); } @Override public void override() { System.out.println(date); } @Override protected void say() { System.out.println("子類B"); } public static void main(String[] args) { 父類A b = new 子類B(); 子類B.override(); } }
注意一:java
在使用 new 來建立對象的時候,會先檢查該類是否繼承自父類,若是是,則會先調用父類的構造方法,該案例中,在 new 子類B() 時,發現 子類B 是 父類A 的子類,因而先調用 父類A 的構造方法,在 父類A 構造方法中,發現調用了 override 方法,因而又去尋找子類 子類B 是否重寫了 override 方法,發現該子類重寫了,則調用子類的 override,打印出 date,而此時 date 還未被初始化,因此值爲 null。 在父類的構造方法執行完畢後,再執行子類的構造方法,此時 date 被初始化了,因此再次調用 override 方法時,則會正確打印出 date。ide
調用方法時,會優先在子類中尋找對應方法,若是子類中不存在,纔會去調用父類中方法。code
注意二:對象
當調用 子類B.age,會打印出什麼呢?是 10 仍是 9 ?繼承
結果是打印出 10,建立對象的時候,實例變量有兩種類型,前面是聲明類型,後面是實際類型class
父類A b = new 子類B();
b 的聲明類型爲 父類A,實際類型爲 子類B。變量
當調用成員變量的時候,會先在聲明類型中尋找該變量,若是該變量存在,則使用聲明類型中的變量值,若是不存在,則在實際類型中去尋找該變量。date
總結:方法
調用成員變量的時候,會先在聲明類型中尋找該變量,若是該變量存在,則使用聲明類型中的變量值,若是不存在,則在實際類型中去尋找該變量。總結
調用方法的時候,優先在子類中尋找對應方法,若是子類中不存在,再調用父類中方法。