繼承時類和類之間的關系,是一個很簡單很直觀的概念,與顯示生活中的繼承(例如兒子繼承了父親財產)類似。
繼承可以理解為一個類從另一個類中獲取方法和屬性的過程。如果類B繼承於類A,那么類B就擁有類A的屬性和方法。
繼承使用extends關鍵字。
例如我們定義了一個People:
1 public class People { 2 public String name;//姓名 3 public String age;//年齡 4 public String sex;//屬性 5 public void say(){ 6 System.out.println("我的名字為"+this.name+",年齡為"+this.age+",性別為"+this.sex); 7 } 8 }
如果現在還需要定義兩個類,一個是Teacher類,而這個類需要有基本的name,age,sex屬性,還需要增加school,subject,seniority屬性。怎么辦呢?我們要重新定義一個類嗎?
完全沒必要,可以先繼承People類,然后在增加自己的屬性即可。例如:
1 public class Teacher extends People{ 2 public String school;//教師所在的學校 3 public String subject;//學科 4 public int seniority;//教齡 5 6 public void say(){ 7 System.out.println("我的名字為"+this.name+",在"+school+"教"+this.subject+",有"+seniority+"年教齡!"); 8 } 9 10 public void lecturing() { 11 System.out.println("我已經" + age + "歲了,還在教育崗位!"); 12 } 13 }
其中
- name和age變量雖然沒有在Teacher中定義,但是已經在People中定義,而Teacher繼承了People類,這樣People中的屬性和方法可以直接拿過來用。
- 而Teacher類繼承了People類,稱Teacher是People類的子類,People是Teacher的父類。
- 子類可以覆蓋父類中的方法。
- 子類可以覆蓋父類除private修飾的以外的所有成員。
構造方法不能被繼承。
繼承是在維護和可靠性的一個偉大進步,如果在People中進行修改,那么Teacher類就會自動修改,而不需要手動去修改。
單繼承性:Java允許一個類僅能繼承一個其他類,即一個類只能有一個父類,這個限制被稱為單繼承性,而接口允許多繼承,彌補了Java類只能單繼承的缺陷。
如果一個類沒有顯式的繼承一個父類,那么這個類的默認父類就是Object類,Object類是所有類的父類。
在上面的基礎上,實現一個教師:
1 public class PeopleDemo { 2 public static void main(String[] args) { 3 Teacher teacher = new Teacher(); 4 teacher.name = "小布"; 5 teacher.age = "70"; 6 teacher.school = "清華大學"; 7 teacher.subject = "JAVA"; 8 teacher.seniority = 12; 9 teacher.say(); 10 teacher.lecturing(); 11 } 12 }
運行結果:
在 Java 編程語言中,對象的初始化是非常結構化的,這樣做是為了保證安全。在前面的模塊中,看到了當一個特定對象被創建時發生了什么。由於繼承性,對象被完成,而且下述行為按順序發生:
- 存儲空間被分配並初始化到 0 值
- 進行顯式初始化
- 調用構造方法
- 層次中的每個類都會發生最后兩個步驟,是從最上層開始。
Java 技術安全模式要求在子類執行任何東西之前,描述父類的一個對象的各個方面都必須初始化。因此,Java 編程語言總是在執行子構造方法前調用父類構造方法的版本。有繼承的類在運行的時候,一定要記得:初始化子類必先初始化父類,這是Java 程序的一個基本運行過程。比如:
1 public class Test extends Parent { 2 private String name; 3 private int age; 4 public Test() { 5 name="Tom"; 6 age=20; 7 } 8 public static void main(String[] args) { 9 Test t = new Test(); 10 System.out.println(t.name + "的年齡是" + t.age); 11 } 12 }
1 public class Parent { 2 private int num = 1; 3 public Parent() { 4 System.out.println("現在初始化父類"); 5 } 6 public void test() { 7 System.out.println("這是父類的test方法"); 8 } 9 }
運行結果:
上述類的基本運行順序是:
- 先運行到第 8 行,這是程序的入口。
- 然后運行到第 9 行,這里要 new 一個 Test,就要調用 Test 的構造方法。
- 就運行到第 4 行,注意:初始化子類必先初始化父類。
- 要先初始化父類,所以運行到第 15 行。
- 然后是第 14 行,初始化一個類,必須先初始化它的屬性。
- 然后是第 16 行。
- 然后是第 17 行,表示父類初始化完成。
- 然后是回到子類,開始初始化屬性,因此運行到第 2 行,然后是第 3 行。
- 子類屬性初始化完過后,才回到子類的構造方法,執行里面的代碼,也就是第 5、6 行。
- 然后是第7 行,表示 new 一個 Test 實例完成。
- 然后回到 main 方法中執行第 10 行。
- 然后是第 11 行。