一、基本概念
接口(Interface),在JAVA編程語言中是一個抽象類型,是抽象方法的集合。接口通常以interface來聲明。一個類通過繼承接口的方式,從而來繼承接口的抽象方法。
如果一個類只由抽象方法和全局常量組成,那麼這種情況下不會將其定義爲一個抽象類。只會定義爲一個接口,所以接口嚴格的來講屬於一個特殊的類,而這個類裏面只有抽象方法和全局常量,就連構造方法也沒有。
範例:定義一個接口
interface A{//定義一個接口
public static final String MSG = "hello";//全局常量
public abstract void print();//抽象方法
}
二、接口的使用
1、由於接口裏面存在抽象方法,所以接口對象不能直接使用關鍵字new進行實例化。接口的使用原則如下:
(1)接口必須要有子類,但此時一個子類可以使用implements關鍵字實現多個接口;
(2)接口的子類(如果不是抽象類),那麼必須要覆寫接口中的全部抽象方法;
(3)接口的對象可以利用子類對象的向上轉型進行實例化。
範例:
package com.wz.interfacedemo;
interface A{//定義一個接口A
public static final String MSG = "hello";//全局常量
public abstract void print();//抽象方法
}
interface B{//定義一個接口B
public abstract void get();
}
class X implements A,B{//X類實現了A和B兩個接口
@Override
public void print() {
System.out.println("接口A的抽象方法print()");
}
@Override
public void get() {
System.out.println("接口B的抽象方法get()");
}
}
public class TestDemo {
public static void main(String[] args){
X x = new X();//實例化子類對象
A a = x;//向上轉型
B b = x;//向上轉型
a.print();
b.get();
}
}
運行結果:
接口A的抽象方法print()
接口B的抽象方法get()
以上的代碼實例化了X類的對象,由於X類是A和B的子類,那麼X類的對象可以變爲A接口或者B接口對象。我們把測試主類代碼改一下:
public class TestDemo {
public static void main(String[] args){
A a = new X();
B b = (B) a;
b.get();
}
}
運行結果:
接口B的抽象方法get()
好,沒任何問題,我們再來做個驗證:
public class TestDemo {
public static void main(String[] args){
A a = new X();
B b = (B) a;
b.get();
System.out.println(a instanceof A);
System.out.println(a instanceof B);
}
運行結果:
接口B的抽象方法get()
true
true
我們發現,從定義結構來講,A和B兩個接口沒有任何直接聯繫,但這兩個接口卻擁有同一個子類。我們不要被類型和名稱所迷惑,因爲實例化的是X子類,而這個類對象屬於B類的對象,所以以上代碼可行,只不過從代碼的編寫規範來講,並不是很好。
2、對於子類而言,除了實現接口外,還可以繼承抽象類。若既要繼承抽象類,同時還要實現接口的話,使用一下語法格式:
class 子類 [extends 父類] [implemetns 接口1,接口2,...] {}
範例:
interface A{//定義一個接口A
public static final String MSG = "hello";//全局常量
public abstract void print();//抽象方法
}
interface B{//定義一個接口B
public abstract void get();
}
abstract class C{//定義一個抽象類C
public abstract void change();
}
class X extends C implements A,B{//X類繼承C類,並實現了A和B兩個接口
@Override
public void print() {
System.out.println("接口A的抽象方法print()");
}
@Override
public void get() {
System.out.println("接口B的抽象方法get()");
}
@Override
public void change() {
System.out.println("抽象類C的抽象方法change()");
}
}
對於接口,裏面的組成只有抽象方法和全局常量,所以很多時候爲了書寫簡單,可以不用寫public abstract 或者public static final。並且,接口中的訪問權限只有一種:public,即:定義接口方法和全局常量的時候就算沒有寫上public,那麼最終的訪問權限也是public,注意不是default。以下兩種寫法是完全等價的:
interface A{
public static final String MSG = "hello";
public abstract void print();
}
等價於
interface A{
String MSG = "hello";
void print();
}
但是,這樣會不會帶來什麼問題呢?如果子類子類中的覆寫方法也不是public,我們來看:
package com.wz.interfacedemo;
interface A{
String MSG = "hello";
void print();
}
class X implements A{
void print() {
System.out.println("接口A的抽象方法print()");
}
}
public class TestDemo {
public static void main(String[] args){
A a = new X();
a.print();
}
}
運行結果:
Exception in thread "main" java.lang.IllegalAccessError: com.wz.interfacedemo.X.print()V
at com.wz.interfacedemo.TestDemo.main(TestDemo.java:22)
這是因爲接口中默認是public修飾,若子類中沒用public修飾,則訪問權限變嚴格了,給子類分配的是更低的訪問權限。所以,在定義接口的時候強烈建議在抽象方法前加上public ,子類也加上:
interface A{
String MSG = "hello";
public void print();
}
class X implements A{
public void print() {
System.out.println("接口A的抽象方法print()");
}
}
3、在Java中,一個抽象類只能繼承一個抽象類,但一個接口卻可以使用extends關鍵字同時繼承多個接口(但接口不能繼承抽象類)。
範例:
interface A{
public void funA();
}
interface B{
public void funB();
}
//C接口同時繼承了A和B兩個接口
interface C extends A,B{//使用的是extends
public void funC();
}
class X implements C{
@Override
public void funA() {
}
@Override
public void funB() {
}
@Override
public void funC() {
}
}
由此可見,從繼承關係來說接口的限制比抽象類少:
(1)一個抽象類只能繼承一個抽象父類,而接口可以繼承多個接口;
(2)一個子類只能繼承一個抽象類,卻可以實現多個接口(在Java中,接口的主要功能是解決單繼承侷限問題)
4、從接口的概念上來講,接口只能由抽象方法和全局常量組成,但是內部結構是不受概念限制的,正如抽象類中可以定義抽象內部類一樣,在接口中也可以定義普通內部類、抽象內部類和內部接口(但從實際的開發來講,用戶自己去定義內部抽象類或內部接口的時候是比較少見的),範例如下,在接口中定義一個抽象內部類:
interface A{
public void funA();
abstract class B{//定義一個抽象內部類
public abstract void funB();
}
}
在接口中如果使用了static去定義一個內接口,它表示一個外部接口:
interface A{
public void funA();
static interface B{//使用了static,是一個外部接口
public void funB();
}
}
class X implements A.B{
@Override
public void funB() {
}
}
三、接口的實際應用(標準定義)
在日常的生活之中,接口這一名詞經常聽到的,例如:USB接口、打印接口、充電接口等等。
如果要進行開發,要先開發出USB接口標準,然後設備廠商纔可以設計出USB設備。
現在假設每一個USB設備只有兩個功能:安裝驅動程序、工作。
定義一個USB的標準:
interface USB { // 操作標準
public void install() ;
public void work() ;
}
在電腦上應用此接口:
class Computer {
public void plugin(USB usb) {
usb.install() ;
usb.work() ;
}
}
定義USB設備—手機:
class Phone implements USB {
public void install() {
System.out.println("安裝手機驅動程序。") ;
}
public void work() {
System.out.println("手機與電腦進行工作。") ;
}
}
定義USB設備—打印機:
class Print implements USB {
public void install() {
System.out.println("安裝打印機驅動程序。") ;
}
public void work() {
System.out.println("進行文件打印。") ;
}
}
定義USB設備—MP3:
class MP3 implements USB {
public void install() {
System.out.println("安裝MP3驅動程序。") ;
}
public void work() {
System.out.println("進行MP3拷貝。") ;
}
}
測試主類:
public class TestDemo {
public static void main(String args[]) {
Computer c = new Computer() ;
c.plugin(new Phone()) ;
c.plugin(new Print()) ;
c.plugin(new MP3());
}
}
運行結果:
安裝手機驅動程序。
手機與電腦進行工作。
安裝打印機驅動程序。
進行文件打印。
安裝MP3驅動程序。
進行MP3拷貝。
可以看出,不管有多少個USB接口的子類,都可以在電腦上使用。
在現實生活中,標準的概念隨處可見,而在程序裏標準使用接口定義的。
未完待續。。。