Java 教程

Java 控制語句

面向物件程式設計

Java 內建類

Java 檔案處理

Java 錯誤和異常

Java 多執行緒

Java 同步

Java 網路

Java 集合

Java 介面

Java 資料結構

Java 集合演算法

高階 Java

Java 雜項

Java API 和框架

Java 類引用

Java 有用資源

Java - 抽象



根據詞典,**抽象**是指處理思想而不是事件的特性。例如,當您考慮電子郵件的情況時,傳送電子郵件後發生的事情等複雜細節,您的電子郵件伺服器使用的協議對使用者是隱藏的。因此,要傳送電子郵件,您只需鍵入內容,提及接收者的地址,然後單擊發送。

Java 抽象

抽象是向用戶隱藏實現細節的過程,只向用戶提供功能。換句話說,使用者將瞭解物件的功能而不是其工作方式。在 Java 程式設計中,抽象是使用**抽象類**和**介面**實現的。

Java 抽象類

在宣告中包含**abstract**關鍵字的Java 類稱為抽象類。

  • Java 抽象類可能包含也可能不包含抽象方法,即沒有主體的方法 (public void get(); )

  • 但是,如果一個類至少有一個抽象方法,則該類**必須**宣告為抽象類。

  • 如果一個類被宣告為抽象類,則不能對其進行例項化。

  • 要使用抽象類,您必須從另一個類繼承它,並在其中為抽象方法提供實現。

  • 如果您繼承了一個抽象類,則必須為其中的所有抽象方法提供實現。

示例:Java 抽象類

本節為您提供 Java 抽象類的示例。要在 Java 中建立抽象類,只需在類宣告中,在 class 關鍵字之前使用**abstract**關鍵字。

/* File name : Employee.java */
public abstract class Employee {
   private String name;
   private String address;
   private int number;

   public Employee(String name, String address, int number) {
      System.out.println("Constructing an Employee");
      this.name = name;
      this.address = address;
      this.number = number;
   }
   
   public double computePay() {
     System.out.println("Inside Employee computePay");
     return 0.0;
   }
   
   public void mailCheck() {
      System.out.println("Mailing a check to " + this.name + " " + this.address);
   }

   public String toString() {
      return name + " " + address + " " + number;
   }

   public String getName() {
      return name;
   }
 
   public String getAddress() {
      return address;
   }
   
   public void setAddress(String newAddress) {
      address = newAddress;
   }
 
   public int getNumber() {
      return number;
   }
}

您可以觀察到,除了抽象方法外,Employee 類與 Java 中的普通類相同。該類現在是抽象的,但它仍然有三個欄位、七個方法和一個建構函式。

現在您可以嘗試以下方式例項化 Employee 類:

/* File name : AbstractDemo.java */
public class AbstractDemo {

   public static void main(String [] args) {
      /* Following is not allowed and would raise error */
      Employee e = new Employee("George W.", "Houston, TX", 43);
      System.out.println("\n Call mailCheck using Employee reference--");
      e.mailCheck();
   }
}

abstract class Employee {
   private String name;
   private String address;
   private int number;

   public Employee(String name, String address, int number) {
      System.out.println("Constructing an Employee");
      this.name = name;
      this.address = address;
      this.number = number;
   }
   
   public double computePay() {
     System.out.println("Inside Employee computePay");
     return 0.0;
   }
   
   public void mailCheck() {
      System.out.println("Mailing a check to " + this.name + " " + this.address);
   }

   public String toString() {
      return name + " " + address + " " + number;
   }

   public String getName() {
      return name;
   }
 
   public String getAddress() {
      return address;
   }
   
   public void setAddress(String newAddress) {
      address = newAddress;
   }
 
   public int getNumber() {
      return number;
   }
}

編譯上述類時,會收到以下錯誤:

Employee.java:46: Employee is abstract; cannot be instantiated
      Employee e = new Employee("George W.", "Houston, TX", 43);
                   ^
1 error

繼承 Java 抽象類

我們可以像在以下方式中繼承具體類一樣繼承 Employee 類的屬性:

示例:在 Java 中繼承抽象類

/* File name : Salary.java */
public class Salary extends Employee {
   private double salary;   // Annual salary
   
   public Salary(String name, String address, int number, double salary) {
      super(name, address, number);
      setSalary(salary);
   }
   
   public void mailCheck() {
      System.out.println("Within mailCheck of Salary class ");
      System.out.println("Mailing check to " + getName() + " with salary " + salary);
   }
 
   public double getSalary() {
      return salary;
   }
   
   public void setSalary(double newSalary) {
      if(newSalary >= 0.0) {
         salary = newSalary;
      }
   }
   
   public double computePay() {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
}

這裡,您不能例項化 Employee 類,但您可以例項化 Salary 類,並使用此例項訪問 Employee 類中的所有三個欄位和七個方法,如下所示。

/* File name : AbstractDemo.java */
public class AbstractDemo {

   public static void main(String [] args) {
      Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
      Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
      System.out.println("Call mailCheck using Salary reference --");
      s.mailCheck();
      System.out.println("\n Call mailCheck using Employee reference--");
      e.mailCheck();
   }
}
abstract class Employee {
   private String name;
   private String address;
   private int number;

   public Employee(String name, String address, int number) {
      System.out.println("Constructing an Employee");
      this.name = name;
      this.address = address;
      this.number = number;
   }
   
   public double computePay() {
     System.out.println("Inside Employee computePay");
     return 0.0;
   }
   
   public void mailCheck() {
      System.out.println("Mailing a check to " + this.name + " " + this.address);
   }

   public String toString() {
      return name + " " + address + " " + number;
   }

   public String getName() {
      return name;
   }
 
   public String getAddress() {
      return address;
   }
   
   public void setAddress(String newAddress) {
      address = newAddress;
   }
 
   public int getNumber() {
      return number;
   }
}
class Salary extends Employee {
   private double salary;   // Annual salary
   
   public Salary(String name, String address, int number, double salary) {
      super(name, address, number);
      setSalary(salary);
   }
   
   public void mailCheck() {
      System.out.println("Within mailCheck of Salary class ");
      System.out.println("Mailing check to " + getName() + " with salary " + salary);
   }
 
   public double getSalary() {
      return salary;
   }
   
   public void setSalary(double newSalary) {
      if(newSalary >= 0.0) {
         salary = newSalary;
      }
   }
   
   public double computePay() {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
}

輸出

Constructing an Employee
Constructing an Employee
Call mailCheck using Salary reference --
Within mailCheck of Salary class 
Mailing check to Mohd Mohtashim with salary 3600.0

 Call mailCheck using Employee reference--
Within mailCheck of Salary class 
Mailing check to John Adams with salary 2400.0

Java 抽象方法

如果您希望一個類包含特定的方法,但希望該方法的實際實現由子類確定,則可以在父類中將該方法宣告為抽象方法。

  • **abstract**關鍵字用於將方法宣告為抽象方法。

  • 在方法宣告中,您必須在方法名稱之前放置abstract關鍵字。

  • 抽象方法包含方法簽名,但不包含方法體。

  • 抽象方法的末尾將使用分號(;),而不是大括號。

示例 1:在 Java 中實現抽象方法

以下是抽象方法的示例。

public abstract class Employee {
   private String name;
   private String address;
   private int number;
   
   public abstract double computePay();
   // Remainder of class definition
}

將方法宣告為抽象有兩個結果:

  • 包含它的類必須宣告為抽象類。

  • 任何繼承當前類的類都必須重寫抽象方法或將其自身宣告為抽象類。

注意:最終,子類必須實現抽象方法;否則,您將擁有一個無法例項化的抽象類層次結構。

假設 Salary 類繼承了 Employee 類,那麼它應該像下面這樣實現computePay()方法:

/* File name : Salary.java */
public class Salary extends Employee {
   private double salary;   // Annual salary
  
   public double computePay() {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
   // Remainder of class definition
}

示例 2:在 Java 中實現抽象方法

以下示例展示了抽象方法的概念。

/* File name : AbstractDemo.java */
public class AbstractDemo {
   public static void main(String [] args) {
      Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
      System.out.println("salary: " + s.computePay());
   }
}
abstract class Employee {
   private String name;
   private String address;
   private int number;

   public Employee(String name, String address, int number) {
      System.out.println("Constructing an Employee");
      this.name = name;
      this.address = address;
      this.number = number;
   }

   public abstract double computePay();
      // Remainder of class definition

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getAddress() {
      return address;
   }

   public void setAddress(String address) {
      this.address = address;
   }

   public int getNumber() {
      return number;
   }

   public void setNumber(int number) {
      this.number = number;
   }
}
class Salary extends Employee {
   private double salary;   // Annual salary

   public Salary(String name, String address, int number, double salary) {
      super(name, address, number);
      this.salary = salary;
   }

   public double computePay() {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
   // Remainder of class definition
}

輸出

Constructing an Employee
Computing salary pay for Mohd Mohtashim
salary: 69.23076923076923
廣告