繼承(extends)java
class Demo1_Extends { public static void main(String[] args) { Cat c = new Cat(); c.color = "花"; c.leg = 4; c.eat(); c.sleep(); System.out.println(c.leg + "..." + c.color); } } /* * A:繼承(extends) * 讓類與類之間產生關係,子父類關係 * B:繼承案例演示: * 動物類,貓類,狗類 * 定義兩個屬性(顏色,腿的個數)兩個功能(吃飯,睡覺) * C:案例演示 * 使用繼承前 * D:案例演示 * 使用繼承後 */ class Animal { String color; //動物的顏色 int leg; //動物腿的個數 public void eat() { //吃飯的功能 System.out.println("吃飯"); } public void sleep() { //睡覺的功能 System.out.println("睡覺"); } } class Cat extends Animal { } class Dog extends Animal { } /* extends是繼承的意思 Animal是父類 Cat和Dog都是子類 */
B:繼承的弊端程序員
類的耦合性加強了。面試
開發的原則:高內聚,低耦合。jvm
class Demo2_Extends { public static void main(String[] args) { DemoC d = new DemoC(); d.show(); } } /* * A:Java中類的繼承特色 * a:Java只支持單繼承,不支持多繼承。(一個兒子只能有一個爹) * 有些語言是支持多繼承,格式:extends 類1,類2,... * b:Java支持多層繼承(繼承體系) * B:案例演示 * Java中類的繼承特色 * 若是想用這個體系的全部功能用最底層的類建立對象 * 若是想看這個體系的共性功能,看最頂層的類 */ class DemoA { public void show() { System.out.println("DemoA"); } } class DemoB extends DemoA { public void method() { System.out.println("DemoB"); } } class DemoC extends DemoB { public void print() { System.out.println("DemoC"); } }
B:何時使用繼承this
採用假設法。 若是有兩個類A,B。只有他們符合A是B的一種,或者B是A的一種,就能夠考慮使用繼承。spa
class Demo3_Extends { public static void main(String[] args) { Son s = new Son(); s.show(); } } /* * A:繼承的注意事項 * a:子類只能繼承父類全部非私有的成員(成員方法和成員變量) * b:子類不能繼承父類的構造方法,可是能夠經過super(立刻講)關鍵字去訪問父類構造方法。 * c:不要爲了部分功能而去繼承 * 項目經理 姓名 工號 工資 獎金 * 程序員 姓名 工號 工資 */ class Father { private String name; private void show() { System.out.println("Hello World!"); } } class Son extends Father { }
class Demo4_Extends { public static void main(String[] args) { Son s = new Son(); s.print(); } } /* * A:案例演示 * a:不一樣名的變量 * b:同名的變量 子父類出現同名的變量只是在講課中舉例子有,在開發中是不會出現這種狀況的 子類繼承父類就是爲了使用父類的成員,那麼若是定義了同名的成員變量沒有意義了 */ class Father { int num1 = 10; int num2 = 30; } class Son extends Father { int num2 = 20; public void print() { System.out.println(this.num1); //this既能夠調用本類的,也能夠調用父類的(本類沒有的狀況下) System.out.println(this.num2); //就近原則,子類有就不用父類的了 System.out.println(super.num2); } }
B:爲何呢?code
因此,子類初始化以前,必定要先完成父類數據的初始化。對象
其實:繼承
class Demo5_Extends { public static void main(String[] args) { Son s = new Son(); } } /* * A:案例演示 * 子類中全部的構造方法默認都會訪問父類中空參數的構造方法 * B:爲何呢? * 由於子類會繼承父類中的數據,可能還會使用父類的數據。 * 因此,子類初始化以前,必定要先完成父類數據的初始化。 * 其實: * 每個構造方法的第一條語句默認都是:super() Object類最頂層的父類。 */ class Father extends Object { public Father() { super(); System.out.println("Father 的構造方法"); } } class Son extends Father { public Son() { super(); //這是一條語句,若是不寫,系統會默認加上,用來訪問父類中的空參構造 System.out.println("Son 的構造方法"); } }
class Demo6_Extends { public static void main(String[] args) { Son s1 = new Son(); System.out.println(s1.getName() + "..." + s1.getAge()); System.out.println("--------------------"); Son s2 = new Son("張三",23); System.out.println(s2.getName() + "..." + s2.getAge()); } } /* * A:案例演示 * 父類沒有無參構造方法,子類怎麼辦? * super解決 * this解決 * B:注意事項 * super(…)或者this(….)必須出如今構造方法的第一條語句上 */ class Father { private String name; //姓名 private int age; //年齡 public Father() { //空參構造 System.out.println("Father 空參構造"); } public Father(String name,int age) { //有參構造 this.name = name; this.age = age; System.out.println("Father 有參構造"); } public void setName(String name) { //設置姓名 this.name = name; } public String getName() { //獲取姓名 return name; } public void setAge(int age) { //設置年齡 this.age = age; } public int getAge() { //獲取年齡 return age; } } class Son extends Father { public Son() { //空參構造 this("王五",25); //本類中的構造方法 //super("李四",24); //調用父類中的構造方法 System.out.println("Son 空參構造"); } public Son(String name,int age) { //有參構造 super(name,age); System.out.println("Son 有參構造"); } }
class Fu{ public int num = 10; public Fu(){ System.out.println("fu"); } } class Zi extends Fu{ public int num = 20; public Zi(){ //super(); System.out.println("zi"); } public void show(){ int num = 30; System.out.println(num); System.out.println(this.num); //調用本類的成員變量20 System.out.println(super.num); //調用父類的成員變量10 } } class Test1_Extends { public static void main(String[] args) { Zi z = new Zi(); z.show(); } }
class Test2_Extends { public static void main(String[] args) { Zi z = new Zi(); } /* 1,jvm調用了main方法,main進棧 2,遇到Zi z = new Zi();會先將Fu.class和Zi.class分別加載進內存,再建立對象,當Fu.class加載進內存 父類的靜態代碼塊會隨着Fu.class一塊兒加載,當Zi.class加載進內存,子類的靜態代碼塊會隨着Zi.class一塊兒加載 第一個輸出,靜態代碼塊Fu,第二個輸出靜態代碼塊Zi 3,走Zi類的構造方法,由於java中是分層初始化的,先初始化父類,再初始化子類,因此先走的父類構造,可是在執行 父類構造時,發現父類有構造代碼塊,構造代碼塊是優先於構造方法執行的因此 第三個輸出構造代碼塊Fu,第四個輸出構造方法Fu 4,Fu類初始化結束,子類初始化,第五個輸出的是構造代碼塊Zi,構造方法Zi */ } class Fu { static { System.out.println("靜態代碼塊Fu"); } { System.out.println("構造代碼塊Fu"); } public Fu() { System.out.println("構造方法Fu"); } } class Zi extends Fu { static { System.out.println("靜態代碼塊Zi"); } { System.out.println("構造代碼塊Zi"); } public Zi() { System.out.println("構造方法Zi"); } }
看程序寫結果1 class Fu{ public int num = 10; public Fu(){ System.out.println("fu"); } } class Zi extends Fu{ public int num = 20; public Zi(){ System.out.println("zi"); } public void show(){ int num = 30; System.out.println(num); System.out.println(this.num); //調用本類成員變量20 System.out.println(super.num);//調用父類成員變量10 } } class Test1_Extends { public static void main(String[] args) { Zi z = new Zi(); z.show(); } } 看程序寫結果2 class Fu { static { System.out.println("靜態代碼塊Fu"); } { System.out.println("構造代碼塊Fu"); } public Fu() { System.out.println("構造方法Fu"); } } class Zi extends Fu { static { System.out.println("靜態代碼塊Zi"); } { System.out.println("構造代碼塊Zi"); } public Zi() { System.out.println("構造方法Zi"); } } Zi z = new Zi(); 請執行結果。
class Demo7_Extends { public static void main(String[] args) { Son s = new Son(); s.print(); s.method(); } } /* * a:不一樣名的方法 * b:同名的方法 */ class Father { public void print() { System.out.println("Fu print"); } } class Son extends Father { public void method() { System.out.println("Zi Method"); } public void print() { super.print(); //super能夠調用父類的成員方法 System.out.println("Zi print"); } }