繼承java
1.1 繼承的概述程序員
在現實生活中,繼承通常指的是子女繼承父輩的財產。在程序中,繼承描述的是事物之間的所屬關係,經過繼承可使多種事物之間造成一種關係體系。算法
格式: class 子類 extends 父類 {}
1.2 繼承的格式&使用ide
在程序中,若是想聲明一個類繼承另外一個類,須要使用extends關鍵字函數
1.2.1 案例代碼一學習
package com.gao_01; /* * 繼承:多個類有共同的成員變量和成員方法,抽取到另一個類中(父類),在讓多個類去繼承這個父類,咱們的多個類就能夠獲取到父類中的成員了。 * extends * */ public class ExtendsDemo { public static void main(String[] args) { DotA1 d = new DotA1(); d.start(); LOL1 l = new LOL1(); l.start(); } } class Game1 { String name; double version;//版本號 String agent;//代理商 public void start() { System.out.println("遊戲啓動了"); } public void stop() { System.out.println("遊戲關閉了"); } } class DotA1 extends Game1 { /*String name; double version;//版本號 String agent;//代理商 public void start() { System.out.println("遊戲啓動了"); } public void stop() { System.out.println("遊戲關閉了"); }*/ } class LOL1 extends Game1 { /*String name; double version;//版本號 String agent;//代理商 public void start() { System.out.println("遊戲啓動了"); } public void stop() { System.out.println("遊戲關閉了"); }*/ }
1.3 繼承的特色this
再類的繼承中,須要注意一些問題,具體以下:spa
一、 在java中,類只支持單繼承,不容許多繼承,也就是說一個類只能有一個直接父類,例以下面這種狀況是不合法的。代理
class A{} class B{} class C extends A,B{} // C類不能夠同時繼承A類和B類
二、 多繼承能夠繼承一個父類,例以下面這種狀況是容許的。code
class A{} class B extends A{} class C extends A{} // 類B和類C均可以繼承類A
三、在Java中,多層繼承是能夠的,即一個類的父類能夠再去繼承另外的父類,例如C類繼承自B類,而B類又能夠去繼承A類,這時,C類也可稱做A類的子類。下面這種狀況是容許的。
class A{} class B extends A{} // 類B繼承類A,類B是類A的子類 class C extends B{} // 類C繼承類B,類C是類B的子類,同時也是類A的子類
四、在Java中,子類和父類是一種相對概念,也就是說一個類是某個類父類的同時,也能夠是另外一個類的子類。例如上面的這種狀況中,B類是A類的子類,同時又是C類的父類
1.3.1 案例代碼二
package com.gao_01; /* * Java中繼承的特色: * Java語言只支持單一繼承,只能繼承一個父類(一個兒子只能有一個親爹) * Java語言支持多層繼承(一個兒子能夠有一個親爹,還能夠有一個親爺爺) * */ public class ExtendsDemo2 { public static void main(String[] args) { LOL l = new LOL(); l.update(); l.start(); } } class Game { public void start() { System.out.println("遊戲啓動了"); } } class PCGame extends Game { public void update() { System.out.println("PCGame更新了"); } } class MobileGame extends Game { public void update() { System.out.println("MobileGame更新了"); } } class LOL extends PCGame { }
1.4 繼承中成員變量的特色
A:子類只能獲取父類非私有成員
子父類中成員變量的名字不同直接獲取父類的成員變量
子父類中成員變量名字是同樣的獲取的是子類的成員變量
B:就近原則:誰離我近我 就用誰
若是有局部變量就使用局部變量
若是沒有局部變量,有子類的成員變量就使用子類的成員變量
若是沒有局部變量和子類的成員變量,有父類的成員變量就使用父類的成員變量
C: super:能夠獲取父類的成員變量和成員方法,用法和this是類似的
1.4.1 案例代碼三
package com.gao_01; /* * 繼承中成員變量的特色 * 子類只能獲取父類非私有成員 * 子父類中成員變量的名字不同直接獲取父類的成員變量 * 子父類中成員變量名字是同樣的獲取的是子類的成員變量 * * 就近原則:誰離我近我就用誰 * 若是有局部變量就使用局部變量 * 若是沒有局部變量,有子類的成員變量就使用子類的成員變量 * 若是沒有局部變量和子類的成員變量,有父類的成員變量就使用父類的成員變量 * 啥都沒有,出錯了!!! * * super:能夠獲取父類的成員變量和成員方法,用法和this是類似的 */ public class ExtendsDemo3 { public static void main(String[] args) { Kid3 k = new Kid3(); k.show(); } } class Dad3 { String name = "小紅"; } class Kid3 extends Dad3 { String name = "四蔥"; public void show() { String name = "五蔥"; System.out.println(super.name); System.out.println(this.name); System.out.println(name); } }
1.5 繼承中成員方法的特色&方法重寫
1.5.1 案例代碼四
A: 若是子類中沒有這個方法,調用父類的
package com.gao_01; /* * 繼承中成員方法的特色 * 子類中沒有這個方法,調用父類的 */ public class ExtendsDemo4 { public static void main(String[] args) { Kid4 k = new Kid4(); k.eat(); } } class Dad4 { public void eat() { System.out.println("小酌兩口"); System.out.println("去睡覺了"); } } class Kid4 extends Dad4 { }
1.5.2 案例代碼五
B: 子類中重寫了這個方法,調用子類的
方法的重寫:在子父類當中,子類的方法和父類的徹底同樣,子類重寫了父類的方
法(覆蓋),當子類重寫了父類的方法以後,使用子類對象調用的就是子類的方法
package com.gao_01; /* * 繼承中成員方法的特色 * 子類中沒有這個方法,調用父類的 * 子類中重寫了這個方法,調用子類的 * 方法的重寫:在子父類當中,子類的方法和父類的徹底同樣,子類重寫了父類的方法(覆蓋),當子類重寫了父類的方法以後,使用子類對象調用的就是子類的方法 方法的重載:在一個類中,有多個重名的方法,可是其參數不同(參數的個數,參數的類型,參數的順序),和返回值無關 */ public class ExtendsDemo4 { public static void main(String[] args) { Kid4 k = new Kid4(); k.eat(); } } class Dad4 { public void eat() { System.out.println("小酌兩口"); System.out.println("去睡覺了"); } } class Kid4 extends Dad4 { public void eat() { System.out.println("好好吃飯"); } }
1.6 方法重寫的應用場景&注意事項
方法重寫的應用場景:當父類的方法不能徹底知足子類使用的時候,既能夠保留父類的功能(沿襲、傳承),還能夠有本身特有的功能
方法重寫的注意事項:
不能夠重寫父類私有的成員方法,壓根就看不到父類的私有成員
子類重寫父類方法,權限必須大於等於父類方法的權限
註解:
@Override:方法重寫,說明下面的方法是重寫父類的方法
1.6.1 案例代碼六
package com.gao_03; /* * 方法重寫的應用場景:當父類的方法不能徹底知足子類使用,這個時候子類重寫父類的方法, * 並能夠在方法中使用關鍵字super調用父類的方法,這樣作便可以保有父類的功能,也能夠擁有子類特有的功能 * 方法重寫的注意事項: * 不能重寫父類私有的方法 * 權限必須大於等於父類方法的權限 * * 註解:@ * */ public class ExtendsDemo5 { public static void main(String[] args) { NewPhone np = new NewPhone(); np.call(); } } class Phone { void call() { System.out.println("打電話"); } } class NewPhone extends Phone { @Override public void call() { System.out.println("錄音"); //System.out.println("打電話"); //super.call(); } }
1.7 繼承中構造方法的執行順序
A: super(實參列表);語句 在子類的構造方法中使用,用來調用父類中的構造方法(具體哪一 個由傳遞的參數決定),而且只能在構造方法第一行使用
B: this(實參列表); 語句 在類的構造方法中使用,用來調用本類中的其它構造方法(具體哪個由傳遞的參數決定),而且只能在構造方法的第一行使用
1.7.1 案例代碼七
package com.gao_01; /* * 繼承中構造方法的執行順序 * 在子父類中,建立子類對象,調用子類的構造方法, * 在子類的構造方法的第一行代碼若是沒有調用父類的構造或者沒有調用子類的其餘構造,則默認調用父類無參構造 * 爲何要調用父類構造? * 由於須要給父類的成員變量初始化 * 確定會先把父類的構造執行完畢,在去執行子類構造中的其餘代碼 * * 我是父類無參構造 --- 我是子類有參構造 --- 我是子類無參構造 */ public class ExtendsDemo6 { public static void main(String[] args) { //Die d = new Die(); Zi6 z = new Zi6(); } } class Die6 { public Die6() { System.out.println("我是父類無參構造"); } public Die6(int num) { System.out.println("我是父類有參構造"); } } class Zi6 extends Die6 { public Zi6() { //super(1); //super(); this(1);//不會再調用父類的無參構造了 System.out.println("我是子類無參構造"); } public Zi6(int num) { //會默認調用父類無參構造 System.out.println("我是子類有參構造"); } }
1.8 this 與 super區別
1.8.1 案例代碼八
package com.gao_01; /* * this和super的區別 this:當前對象的引用 調用子類的成員變量 調用子類的成員方法 在子類的構造方法第一行調用子類其餘構造方法 super:子類對象的父類引用 調用父類的成員變量 調用父類的成員方法 在子類的構造方法第一行調用父類的構造方法 */ public class ExtendsDemo7 { public static void main(String[] args) { Zi z = new Zi(); z.function(); } } class Die { int num = 10; public Die() { System.out.println("我是父類無參構造"); } public Die(int num) { System.out.println("我是父類有參構造"); } public void method() { System.out.println("我是父類的方法"); } } class Zi extends Die { //int num = 30; public Zi() { //this(1);//第一行不調用子類其餘構造或者是父類構造,默認調用父類無參構造 super(); System.out.println("我是子類無參構造"); } public Zi(int num) { System.out.println("我是子類有參構造"); } public void method() { System.out.println("我是子類的方法"); } public void function() { //this.num = 50; //System.out.println(num); //this.method(); //super.num = 40; //super.method(); System.out.println(this.num); } }
1.9 繼承的優缺點
A:優勢
提升了代碼的複用性
提升了代碼的可維護性
B:缺點:
類的耦合性加強了
開發的原則:高內聚低耦合
內聚:就是本身完成某件事情的能力
耦合:類與類的關係
匿名對象&final
2.1 匿名對象定義&使用
匿名對象即無名對象,直接使用new關鍵字來建立對象
2.1.1 案例代碼九
package com.gao_01; /* * 匿名對象:沒有名字的對象 * 匿名對象的應用場景: * 當方法只調用一次的時候可使用匿名對象 * 能夠看成參數進行傳遞,可是沒法在傳參以前作其餘的事情 * * 注意:匿名對象能夠調用成員變量並賦值,可是賦值並無意義 * */ public class AnonymousObejctDemo { public static void main(String[] args) { //Student s = new Student(); //s.study(); //s.study(); //s.study(); //new Student();//匿名對象,沒有變量引用的對象 //new Student().study(); //new Student().study(); //new Student().study(); //new Student().age = 18; //System.out.println(new Student().age); //Student s = new Student(); //s.age = 18; //s.name = "張三"; //method(s); method(new Student()); } public static void method(Student s) { } } class Student { String name; int age; public void study() { System.out.println("好好學習,高薪就業"); } }
final: 修飾符,能夠用於修飾類、成員方法和成員變量
final所修飾的類:不能被繼承,不能有子類
final所修飾的方法:不能被重寫
final所修飾的變量:是不能夠修改的,是常量
2.2.1 案例代碼十
package com.gao_01; /* * final: 修飾符,能夠用於修飾類、成員方法和成員變量 * final所修飾的類:不能被繼承,不能有子類 * final所修飾的方法:不能被重寫 * final所修飾的變量:是不能夠修改的,是常量 * * 常量: * 字面值常量:1,2,3 * 自定義常量:被final所修飾的成員變量,一旦初始化則不可改變 * * 注意:自定義常量必須初始化,能夠選擇顯示初始化或者構造初始化 * * */ public class FinalDemo { public static void main(String[] args) { //Animal a = new Animal(); //a.eat(); Dog d = new Dog(); //d.eat(); //d.num = 20; System.out.println(d.NUM); } } /*final*/ class Animal { public final void eat() { System.out.println("吃東西"); } } class Dog extends Animal { /*public void eat() {}*/ final int NUM; public Dog() { NUM = 10; } }
抽象類
3.1 抽象類概述
當編寫一個類時,咱們每每會爲該類定義一些方法,這些方法是用來描述該類的功能具體實現方式,那麼這些方法都有具體的方法體。
可是有的時候,某個父類只是知道子類應該包含怎麼樣的方法,可是沒法準確知道子類如何實現這些方法。好比一個圖形類應該有一個求周長的方法,可是不一樣的圖形求周長的算法不同。那該怎麼辦呢?
分析事物時,發現了共性內容,就出現向上抽取。會有這樣一種特殊狀況,就是方法功能聲明相同,但方法功能主體不一樣。那麼這時也能夠抽取,但只抽取方法聲明,不抽取方法主體。那麼此方法就是一個抽象方法。
3.1.1 案例代碼十一
package com.gao_01; /* * abstract:關鍵字,用於修飾方法和類 * 抽象方法:不一樣類的方法是類似,可是具體內容又不太同樣,因此咱們只能抽取他的聲明,沒有具體的方法體,沒有具體方法體的方法就是抽象方法 * 抽象類:有抽象方法的類必須是抽象類 * * 注意:一個類繼承了抽象類須要重寫他全部的抽象方法,不然這個類就得是抽象類 */ public class AbstractDemo { } abstract class Animal1 { public abstract void eat(); //非抽象方法子類能夠不重寫 public void run() { } } class Cat1 extends Animal1 { @Override public void eat() { System.out.println("貓吃魚"); } /*public void eat() { System.out.println("貓吃魚"); }*/ } abstract class Dog1 extends Animal1 { /*public void eat() { System.out.println("狗吃屎"); }*/ }
3.2 抽象類的特色
抽象方法只能在抽象類裏面
抽象類和抽象方法必須被abstract修飾
抽象類不能建立對象(不能實例化)
抽象類中能夠有非抽象的方法
抽象類和類的關係也是繼承
一個類繼承了抽象類要麼重寫全部的抽象方法,要麼他本身是抽象類
3.2.1 案例代碼十二
package com.gao_01; /* * 抽象類的特色: * 抽象方法只能在抽象類裏面 * 抽象類和抽象方法必須被abstract修飾 * 抽象類不能建立對象(不能實例化) * 抽象類中能夠有非抽象的方法 * 抽象類和類的關係也是繼承 * 一個類繼承了抽象類要麼重寫全部的抽象方法,要麼他本身是抽象類 */ public class AbstractDemo2 { public static void main(String[] args) { //Animal a = new Animal(); } } abstract class Animal2 { public abstract void eat(); public void run() { } } class Cat2 extends Animal2 { @Override public void eat() { // TODO Auto-generated method stub } }
3.3 抽象類的成員的特色
A:抽象類的成員特色:
成員變量
能夠有成員變量
能夠有常量
成員方法
能夠有抽象方法
能夠有非抽象方法
構造方法
能夠有構造方法的,須要對抽象類的成員變量進行初始化
3.3.1 案例代碼十三
package com.gao_01; /* * 抽象類的成員特色: * 成員變量 * 能夠有成員變量 * 能夠有常量 * 成員方法 * 能夠有抽象方法 * 能夠有非抽象方法 * 構造方法 * 能夠有構造方法的,須要對抽象類的成員變量進行初始化 * * final:修飾類、成員變量、成員方法 */ public class AbstractDemo3 { public static void main(String[] args) { Dog d = new Dog(); d.barking(); } } abstract class Animal { String name = "哮天犬"; final int num = 10; public Animal() { System.out.println("我是抽象類的構造方法"); } public abstract void eat(); public void run() {} } class Dog extends Animal { public void barking() { System.out.println(name); System.out.println(num); } @Override public void eat() { // TODO Auto-generated method stub } }
3.4 抽象類案例
3.4.1 老師案例
老師類:
屬性:姓名,年齡,性別
行爲:講課
基礎班老師:
屬性:姓名,年齡,性別
行爲:講基礎班課程
就業班老師:
屬性:姓名,年齡,性別
行爲:講就業班課程
package com.gao_02; /* * 基礎班老溼,就業班老溼 * * 共性: * 屬性 姓名,年齡,性別 * 行爲 講課,唱歌 */ public class AbstractTest { public static void main(String[] args) { BasicTeacher bt = new BasicTeacher(); bt.name = "老師一"; bt.teach(); JobTeacher jt = new JobTeacher(); jt.name = "老師二"; jt.teach(); } } abstract class Teacher { String name;//姓名 int age;//年齡 String gender;//性別 //講課 public abstract void teach(); } class BasicTeacher extends Teacher { @Override public void teach() { System.out.println(name + "講基礎班課程"); } } class JobTeacher extends Teacher { @Override public void teach() { System.out.println(name + "講就業班課程"); } }
3.4.2 僱員案例
僱員類:
屬性:姓名,編號,薪水
行爲:工做
程序員:
屬性:姓名,編號,薪水
行爲:寫代碼工做
經理:
屬性:姓名,編號,薪水,獎金
行爲:盯着程序員寫代碼工做
package com.gao_02; /* * 僱員(Employee)示例: 需求: 公司中 程序員(programmer)有姓名(name),工號(id),薪水(pay),工做內容(work)。 項目經理(Manager)除了有姓名(name),工號(id),薪水(pay),還有獎金(bonus),工做內容(work) 員工: 屬性 name,id,pay 行爲 work */ public class AbstractTest2 { public static void main(String[] args) { Programmer p = new Programmer(); p.work(); Manager m = new Manager(); m.work(); } } abstract class Employee { String name;//姓名 String id;//id double pay;//薪水 //工做 public abstract void work(); } class Programmer extends Employee { @Override public void work() { System.out.println("寫代碼"); } } class Manager extends Employee { byte bonus; @Override public void work() { System.out.println("盯着程序員寫代碼"); } }
3.4.3 技師案例
技師:
屬性:姓名,年齡
行爲:服務
足療技師:
屬性:姓名,年齡
行爲:按按腳揉揉肩
其它技師:
屬性:姓名,年齡
行爲:你懂的
package com.gao_02; /* * 足療店 * 技師 * 足療技師 * 其餘技師 * * 共性: * 屬性 姓名,年齡 * 行爲 服務 */ public class AbstractTest3 { public static void main(String[] args) { 足療技師 zl = new 足療技師(); zl.service(); 其餘技師 qt = new 其餘技師(); qt.service(); } } abstract class 技師 { String name;//姓名 int age;//年齡 //服務 public abstract void service(); } class 足療技師 extends 技師 { @Override public void service() { System.out.println("按按腳揉揉肩"); } } class 其餘技師 extends 技師 { @Override public void service() { System.out.println("你懂的"); } }
3.5 抽象類的細節
A:抽象類關鍵字abstract能夠和哪些關鍵字共存?
1.private:
私有的方法子類是沒法繼承到的,也不存在覆蓋,而abstract和private一塊兒使用修飾方法,abstract既要子類去實現這個方法,而private修飾子類根本沒法獲得父類
這個方法。互相矛盾。
2.final:
抽象類不能和final共存,由於抽象類自身沒法建立對象,咱們須要經過子類建立對象,一旦抽象類使用final關鍵字,那麼抽象類就沒有子類
抽象方法不能和final共存,由於抽象方法後期須要被子類重寫,一旦加final沒法重寫
3.static:
抽象方法不能和static關鍵字共存,由於一旦加static咱們就能夠經過類名直接訪問抽象方法,因爲抽象方法沒有方法體,沒有任何意義,也不容許這樣作
B:抽象類中是否能夠不定義抽象方法?
是能夠的,那這個抽象類的存在到底有什麼意義呢?不讓該類建立對象,方法能夠直接讓子類去使用
C:抽象類是否有構造函數?
有,抽象類的構造函數,是由子類的super語句來調用,用於給抽象類中的成員初始化