1. 概述
類用於描述現實生活中一類事物。類中有屬性、方法等成員。
父類中的方法,被它的子類們重寫,子類各自的實現都不盡相同。那么父類的方法聲明和方法主體,只有聲明還有 意義,而方法主體則沒有存在的意義了。
某種情況下,父類只能知道子類應該具備一個怎樣的方法,但是不能夠明確知道如何實現該方法。只能在子類中才能確定如何去實現方法體。例如:所有幾何圖形都應該具備一個計算面積的方法。但是不同的幾何圖形計算面積的方式不同。
我們把沒有方法主體的方法稱為抽象方法。Java語法規定,包含抽象方法 的類就是抽象類。
2. 抽象方法
抽象方法 : 只有方法的聲明,沒有方法體,以分號 ; 結尾,使用 abstract
關鍵字修飾
定義格式:
修飾符 abstract 返回值類型 方法名(參數列表);
代碼舉例:
public abstract void run();
抽象方法不能用private、final、static、native修飾
3. 抽象類
抽象類:包含抽象方法的類。如果一個類包含抽象方法,那么該類必須是抽象類,使用 abstract
關鍵字修飾
定義格式:
public abstract class 類名 {
//抽象類中可以包含變量、常量,抽象方法,非抽象方法
}
代碼舉例:
public abstract class Person {
public abstract void work();
}
抽象類的使用
抽象類不能實例化,不能直接創建對象。抽象類是用來被繼承的,繼承抽象類的子類必須重寫父類所有的抽象方法。否則,該子類也必須聲明為抽象類,使用 abstract
關鍵字修飾
抽象類也是類,因此原來類中可以有的成員,抽象類都可以有,那么抽象類不能直接創建對象,為什么還有構造器呢?供子類調用,子類創建對象時,需要為從父類繼承的屬性初始化。
抽象類不能使用final修飾
public class Teacher extends Person {
public void work() {
System.out.println("講課");
}
}
public class AbstractClassTest {
public static void main(String[] args) {
// 創建子類對象
Teacher t = new Teacher();
// 調用run方法
t.work();
}
}
輸出結果:
講課
此時的方法重寫,是子類對父類抽象方法的完成實現,我們將這種方法重寫的操作,叫做實現方法。
實現:去掉abstract關鍵字,加上方法體{...}
抽象類注意事項:
-
抽象類不能創建對象,如果創建,編譯無法通過而報錯。只能創建其非抽象子類的對象。
理解:假設創建了抽象類的對象,調用抽象的方法,而抽象方法沒有具體的方法體,沒有意義。
-
抽象類中,可以有構造方法,是供子類創建對象時,初始化父類成員使用的。
理解:子類的構造方法中,有默認的super(),需要訪問父類構造方法。
-
抽象類中,可以有成員變量。
理解:子類的共性的成員變量 , 可以定義在抽象父類中。
-
抽象類中,不一定包含抽象方法,但是有抽象方法的類必定是抽象類。
理解:未包含抽象方法的抽象類,聲明為抽象類目的就是不想讓使用者創建該類的對象,通常用於某些特殊的類結構設計。
-
抽象類的子類,必須重寫抽象父類中所有的抽象方法,否則,編譯報錯。除非該子類也是抽象類。
理解:假設不重寫所有抽象方法,則類中可能包含抽象方法。那么創建對象后,調用抽象的方法,沒有意義。
抽象類與普通類的區別
抽象類使用abstract修飾;普通類沒有abstract修飾
抽象類不能實例化;普通類可以實例化
抽象類可以包含抽象方法,也可以包含非抽象方法;普通類不能有抽象方法
4. abstract關鍵字
可以用來修飾的結構:類、方法,不能用來修飾變量、代碼塊、構造器
不能和 abstract 一起使用的修飾符
-
外部類可用修飾符:abstract、final,兩種訪問修飾符:public和缺省。其中abstract和final不能一起修飾類
-
方法可用修飾符:4種訪問修飾符,static、final、abstract、native。不能共存的:
- private,abstract不行 因為private不能被重寫
- static,abstract不行 因為static不能被重寫
- final,abstract不行 因為final不能被重寫
- native,abstract不行 因為都沒有方法體,不知道是什么情況,會有歧義
5. 抽象類簡單案例
5.1案例介紹
某IT公司有多名員工,按照員工負責的工作不同,進行了部門的划分(研發部員工、維護部員工)。研發部根據所需研發的內容不同,又分為JavaEE工程師、Android工程師;維護部根據所需維護的內容不同,又分為網絡維護工程師、硬件維護工程師。
公司的每名員工都有他們自己的員工編號、姓名,並要做它們所負責的工作。
工作內容:
-
JavaEE工程師: 員工號為xxx的 xxx員工,正在研發淘寶網站
-
Android工程師:員工號為xxx的 xxx員工,正在研發淘寶手機客戶端軟件
-
網絡維護工程師:員工號為xxx的 xxx員工,正在檢查網絡是否暢通
-
硬件維護工程師:員工號為xxx的 xxx員工,正在修復打印機
請根據描述,完成員工體系中所有類的定義,並指定類之間的繼承關系。進行XX工程師類的對象創建,完成工作方法的調用。
5.2 案例分析
-
根據上述部門的描述,得出如下的員工體系圖:
-
根據員工信息的描述,確定每個員工都有員工編號、姓名、要進行工作。則,把這些共同的屬性與功能抽取到父類中(員工類),關於工作的內容由具體的工程師來進行指定。
-
創建JavaEE工程師對象,完成工作方法的調用
5.3 示例代碼
定義員工類(抽象類)
public abstract class Employee {
private String id; // 員工編號
private String name; // 員工姓名
public String getId() {
returnid;
}
publicvoid setId(String id) {
this.id = id;
}
public String getName() {
returnname;
}
publicvoid setName(String name) {
this.name = name;
}
//工作方法(抽象方法)
public abstract void work();
}
定義研發部員工類Developer 繼承 員工類Employee
public abstract class Developer extends Employee {
}
定義維護部員工類Maintainer 繼承 員工類Employee
public abstract class Maintainer extends Employee {
}
定義JavaEE工程師 繼承 研發部員工類,重寫工作方法
public class JavaEE extends Developer {
@Override
public void work() {
System.out.println("員工號為 " + getId() + " 的 " + getName() + " 員工,正在研發淘寶網站");
}
}
定義Android工程師 繼承 研發部員工類,重寫工作方法
public class Android extends Developer {
@Override
public void work() {
System.out.println("員工號為 " + getId() + " 的 " + getName() + " 員工,正在研發淘寶手機客戶端軟件");
}
}
定義Network網絡維護工程師 繼承 維護部員工類,重寫工作方法
public class Network extends Maintainer {
@Override
public void work() {
System.out.println("員工號為 " + getId() + " 的 " + getName() + " 員工,正在檢查網絡是否暢通");
}
}
定義Hardware硬件維護工程師 繼承 維護部員工類,重寫工作方法
public class Hardware extends Maintainer {
@Override
public void work() {
System.out.println("員工號為 " + getId() + " 的 " + getName() + " 員工,正在修復打印機");
}
}
在測試類中,創建JavaEE工程師對象,完成工作方法的調用
public class Test {
public static void main(String[] args) {
//創建JavaEE工程師員工對象
JavaEE ee = new JavaEE();
//設置該員工的編號
ee.setId("111111");
//設置該員工的姓名
ee.setName("張偉");
//調用該員工的工作方法
ee.work();
}
}