介面的本質——介面是一種特殊的抽象類別,這種抽象類別裡面只包含常量和方法的定義,而沒有變數和方法的實現。
抽象類別所具有的一些東西介面可以具有,假如一個抽象類別裡面所有的方法全都是抽象的,沒有任何一個方法需要這個抽象類別去實現,並且這個抽象類別裡面所有的變數都是靜態(static)變數,都是不能改變(final)的變數,這時可以把這樣的抽象類別定義為一個介面(interface)。把一個類定義成一個介面的格式是把聲明類的關鍵字class用聲明介面的關鍵字interface替換掉即可。
介面(interface)是一種特殊的抽象類別,在這種抽象類別裡面,所有的方法都是抽象方法,並且這個抽象類別的屬性(即成員變數)都是聲明成“public static final 類型 屬性名稱”這樣的,預設也是聲明成“public static final”即裡面的成員變數都是公用的、靜態,不能改變的。因此在介面裡面聲明常量的時候,可以寫成“public static final 類型 常量名=value(值)”這樣的形式,也可以直接寫成“類型 常量名=value(值)”如:“public static final int id=10”可以直接寫成“int id=10”這樣的形式,因為在介面裡面預設的屬性聲明都是“public static final”的,因此“public static final”可以省略不寫。在介面裡面聲明的抽象方法可以不寫abstract關鍵字來標識,因為介面裡面所有的方法都是抽象的,因此這個“abstract”關鍵字預設都是省略掉的,如在一個介面裡面聲明這樣的三個方法:“public void start()”、“public void run()”、“public void stop()”這三個方法前面都沒有使用abstract關鍵字來標識,可它們就是抽象方法,因為在介面裡面的聲明的方法都是抽象方法,因此在介面裡面的抽象方法都會把abstract關鍵字省略掉,因為預設聲明的方法都是抽象的,所以就沒有必要再寫“abstract”字了,這一點與在抽象類別裡面聲明抽象方法時有所區別,在抽象類別裡面聲明抽象方法是一定要使用“abstract”關鍵字的,而在介面裡面聲明抽象方法可以省略掉“abstract”。注意:在介面裡面聲明的抽象方法預設是“public(公用的)”的,也只能是“public(公用的)”之所以要這樣聲明是為了修正C++裡面多重繼承的時候容易出現問題的地方,C++的多繼承容易出現問題,問題在於多繼承的多個父類之間如果他們有相同的成員變數的時候,這個引用起來會相當地麻煩,並且啟動並執行時候會產生各種各樣的問題。JAVA為了修正這個問題,把介面裡面所有的成員變數全都改成static final,成員變數是static類型,那麼這個成員變數就是屬於整個類裡面的,而不是專屬於某個對象。對於多重繼承來說,在一個子類對象裡面實際上包含有多個父類對象,而對於單繼承來說,子類對象裡面就只有一個父類對象。多繼承子類對象就有多個父類對象,而這些父類對象之間可能又會存在有重複的成員變數,這就非常容易出現問題,因此在JAVA裡面避免了這種問題的出現,採用了介面這種方式來實現多繼承。作為介面來說,一個類可以從介面繼承(或者叫實現介面),這也是多繼承,介面裡面的成員變數不專屬於某個對象,都是靜態成員變數,是屬於整個類的,因此一個類去實現多個介面也是無所謂的,不會存在對象之間互相衝突的問題。實現多個介面,也就實現了多重繼承,而且又避免了多重繼承容易出現問題的地方,這就是用介面實現多重繼承的好處。
1、定義介面
使用interface來定義一個介面。介面定義同類的定義類似,也是分為介面的聲明和介面體,其中介面體由常量定義和方法定義兩部分組成。定義介面的基本格式如下:
[修飾符] interface 介面名 [extends 父介面名列表]{
[public] [static] [final] 常量;
[public] [abstract] 方法;
}
修飾符:可選,用於指定介面的存取權限,可選值為public。如果省略則使用預設的存取權限。
介面名:必選參數,用於指定介面的名稱,介面名必須是合法的Java標識符。一般情況下,要求首字母大寫。
extends: 父介面名列表:選擇性參數,用於指定要定義的介面繼承於哪個父介面。當使用extends關鍵
字時,父介面名為必選參數。
方法:介面中的方法只有定義而沒有被實現。
例如,定義一個用於計算的介面,在該介面中定義了一個常量PI和兩個方法,具體代碼如下:
public interface CalInterface { final float PI=3.14159f;//定義用於表示圓周率的常量PI float getArea(float r);//定義一個用於計算面積的方法getArea() float getCircumference(float r);//定義一個用於計算周長的方法getCircumference() }
注意:
與Java的類檔案一樣,介面檔案的檔案名稱必須與介面名相同。
2、實現介面
介面在定義後,就可以在類中實現該介面。在類中實現介面可以使用關鍵字implements,其基本格式如下:
[修飾符] class <類名> [extends 父類名] [implements 介面列表]{
................
}
修飾符:選擇性參數,用於指定類的存取權限,可選值為public、abstract和final。
類名:必選參數,用於指定類的名稱,類名必須是合法的Java標識符。一般情況下,要求首字母大寫。
extends 父類名:選擇性參數,用於指定要定義的類繼承於哪個父類。當使用extends關鍵字時,父類名為必
選參數。
implements 介面列表:選擇性參數,用於指定該類實現的是哪些介面。當使用implements關鍵字時,介面列表為必選參數。當介面列表中存在多個介面名時,各個介面名之間使用逗號分隔。
在類中實現介面時,方法的名字、傳回值類型、參數的個數及類型必須與介面中的完全一致,並且必須實現介面中的所有方法。例如,編寫一個名稱為Cire的類,該類實現5.7.1節中定義的介面Calculate,具體代碼如下:
public class Cire implements CalInterface { public float getArea(float r) { float area=PI*r*r;//計算圓面積並賦值給變數area return area;//返回計算後的圓面積 } public float getCircumference(float r) { float circumference=2*PI*r; //計算圓周長並賦值給變數circumference return circumference; //返回計算後的圓周長 } public static void main(String[] args) { Cire c = new Cire(); float f = c.getArea(2.0f); System.out.println(Float.toString(f)); } }
在類的繼承中,只能做單重繼承,而實現介面時,一次則可以實現多個介面,每個介面間使用逗號“,”分隔。
這時就可能出現(多個介面中的)常量或方法名衝突的情況,解決該問題時,如果常量衝突,則需要明確指定常量的介面,這可以通過“介面名.常量”實現。如果出現方法衝突時,則只要實現一個方法就可以了。