#抽象類 在面向對象的概念中,全部的對象都是經過類來描繪的,可是反過來,並非全部的類都是用來描繪對象的,若是一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。 抽象類除了不能實例化對象以外,類的其它功能依然存在,成員變量、成員方法和構造方法的訪問方式和普通類同樣。 因爲抽象類不能實例化對象,因此抽象類必須被繼承,才能被使用。也是由於這個緣由,一般在設計階段決定要不要設計抽象類。 父類包含了子類集合的常見的方法,可是因爲父類自己是抽象的,因此不能使用這些方法。 在Java中抽象類表示的是一種繼承關係,一個類只能繼承一個抽象類,而一個類卻能夠實現多個接口。 /* 文件名 : 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; } } /* 文件名 : 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; } } /* 文件名 : 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(); } } 輸出 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. #抽象方法 若是你想設計這樣一個類,該類包含一個特別的成員方法,該方法的具體實現由它的子類肯定,那麼你能夠在父類中聲明該方法爲抽象方法。 Abstract 關鍵字一樣能夠用來聲明抽象方法,抽象方法只包含一個方法名,而沒有方法體。 抽象方法沒有定義,方法名後面直接跟一個分號,而不是花括號。 public abstract class Employee { private String name; private String address; private int number; public abstract double computePay(); //其他代碼 } 抽象類纔有抽象方法。 繼承抽象方法的子類必須重寫該方法。不然,該子類也必須聲明爲抽象類。 最終,必須有子類實現該抽象方法,不然,從最初的父類到最終的子類都不能用來實例化對象。 1. 抽象類不能被實例化(初學者很容易犯的錯),若是被實例化,就會報錯,編譯沒法經過。只有抽象類的非抽象子類能夠建立對象。 2. 抽象類中不必定包含抽象方法,可是有抽象方法的類一定是抽象類。 3. 抽象類中的抽象方法只是聲明,不包含方法體,就是不給出方法的具體實現也就是方法的具體功能。 4. 構造方法,類方法(用 static 修飾的方法)不能聲明爲抽象方法。 5. 抽象類的子類必須給出抽象類中的抽象方法的具體實現,除非該子類也是抽象類。 /* 文件名 : Employee.java */ public abstract class Employee { private String name; private String address; private int number; public abstract double computePay(); //其他代碼 } /* 文件名 : 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; } //其他代碼 } #接口 本例定義接口AreaInterface,其中有靜態常量pai和求面積的抽象方法area()。類Circle和類Rectangle實現了AreaInterface接口,即爲接口中的抽象方法area()編寫了知足各自要求的方法體,分別求圓形和長方形的面積。 /* 文件名 : AreaInterface.java */ package jiekou; public interface AreaInterface{ double pai=Math.PI; double area(); } /* 文件名 : Circle.java */ package jiekou; public class Circle implements AreaInterface{ double r; public Circle(double x){ r=x; } //實現接口中的抽象方法,求圓面積 public double area(){ return pai * r * r; } public String toString(){ return "圓:r="+r+"\tarea="+area(); } } /* 文件名 : Rectangle.java */ package jiekou; public class Rectangle implements AreaInterface{ double x,y; public Rectangle(double a,double b){ x=a; y=b; } public double area()//實現接口中的抽象方法,求長方形面積 { return x * y; } public String toString() { return "長方形:x="+x+";y="+y+"\t" area=+area(); } } Java接口和Java抽象類最大的一個區別,就在於Java抽象類能夠提供某些方法的部分實現,而Java接口不能夠,這大概就是Java抽象類惟一的優勢吧,但這個優勢很是有用。若是向一個抽象類里加入一個新的具體方法時,那麼它全部的子類都一會兒都獲得了這個新方法,而Java接口作不到這一點,若是向一個Java接口裏加入一個新方法,全部實現這個接口的類就沒法成功經過編譯了,由於你必須讓每個類都再實現這個方法才行,這顯然是Java接口的缺點。 一個抽象類的實現只能由這個抽象類的子類給出,也就是說,這個實現處在抽象類所定義出的繼承的等級結構中,而因爲Java語言的單繼承性,因此抽象類做爲類型定義工具的效能大打折扣。在這一點上,Java接口的優點就出來了,任何一個實現了一個Java接口所規定的方法的類均可以具備這個接口的類型,而一個類能夠實現任意多個Java接口,從而這個類就有了多種類型。 不難看出,Java接口是定義混合類型的理想工具,混合類代表一個類不只僅具備某個主類型的行爲,並且具備其餘的次要行爲。 在語法上,抽象類和接口有着如下不一樣: 1.abstract class在Java語言中表示的是一種繼承關係,一個類只能使用一次繼承關係。可是,一個類卻能夠實現多個interface。 繼承抽象類使用的是extends關鍵字,實現接口使用的是implements關鍵字,繼承寫在前面,實現接口寫在後面。若是實現多個接口,中間用逗號分隔。例: public class Main extends JApplet public class Main implements Runnable public class Main extends JApplet implements ActionListener public class Main extends JApplet implements ActionListener, Runnable 2.在abstract class中能夠有本身的數據成員,也能夠有非abstract的成員方法,而在interface中,只可以有靜態的不能被修改的數據成員(也就是必須是static final的,不過在 interface中通常不定義數據成員),全部的成員方法都是abstract的。 3.abstract class和interface所反映出的設計理念不一樣。其實abstract class表示的是"is-a"關係,interface表示的是"like-a"關係。 4.實現接口的類必須實現其中的全部方法,繼承自抽象類的子類實現全部的抽象方法。抽象類中能夠有非抽象方法。接口中則不能有實現方法。 5.接口中定義的變量默認是public static final 型,且必須給其初值,因此實現類中不能從新定義,也不能改變其值。 6.抽象類中的變量默認具備 friendly權限,其值能夠在子類中從新定義,也能夠從新賦值。 7.接口中的方法默認都是 public abstract 類型的。 參考: https://baike.baidu.com/item/java%E6%8E%A5%E5%8F%A3/4939170?noadapt=1 https://www.runoob.com/java/java-abstraction.html