基本概念
接口(Interface),在Java編程語言中是一個(gè)抽象類型琐旁,是抽象方法的集合。接口通常以interface來聲明信殊。一個(gè)類通過繼承接口的方式挽绩,從而來繼承接口的抽象方法。
如果一個(gè)類只由抽象方法和全局常量組成堰塌,那么這種情況下不會(huì)將其定義為一個(gè)抽象類赵刑。只會(huì)定義為一個(gè)接口,所以接口嚴(yán)格的來講屬于一個(gè)特殊的類场刑,而這個(gè)類里面只有抽象方法和全局常量料睛,就連構(gòu)造方法也沒有。
例子摇邦,定義一個(gè)接口
interface C{//定義一個(gè)接口
public static final String MSG = "hello";//全局常量
public abstract void print();//抽象方法
}
接口的使用
1.由于接口里面存在抽象方法恤煞,所以接口對(duì)象不能直接使用關(guān)鍵字new進(jìn)行實(shí)例化。接口的使用原則如下:
(1)接口必須要有子類施籍,但此時(shí)一個(gè)子類可以使用implements關(guān)鍵字實(shí)現(xiàn)多個(gè)接口居扒;
(2)接口的子類(如果不是抽象類),那么必須要覆寫接口中的全部抽象方法
(3)接口的對(duì)象可以利用子類對(duì)象的向上轉(zhuǎn)型進(jìn)行實(shí)例化
舉例:
interface C{//定義一個(gè)接口
public static final String MSG = "hello";//全局常量
public abstract void print();//抽象方法
}
interface D{
public abstract void get();
}
class X implements C,D{
@Override
public void print() {
System.out.println("接口C的抽象方法print()");
}
@Override
public void get() {
System.out.println("接口D的抽象方法get()");
}
}
class TestDemo{
public static void main(String[] args){
X x = new X();//實(shí)例化子類對(duì)象
C a = x;//向上轉(zhuǎn)型
D b = x;//向上轉(zhuǎn)型
a.print();
b.get();
}
}
運(yùn)行結(jié)果
接口C的抽象方法print()
接口D的抽象方法get()
以上的代碼實(shí)例化了X類的對(duì)象丑慎,由于X類是A和B的子類喜喂,那么X類的對(duì)象可以變?yōu)锳接口或者B接口對(duì)象。我們把測試主類代碼改一下
class TestDemo{
public static void main(String[] args){
C a = new X();
D b = (D) a;
b.get();
}
}
運(yùn)行結(jié)果為
接口D的抽象方法get()
再做一個(gè)驗(yàn)證
class TestDemo{
public static void main(String[] args){
C a = new X();
D b = (D) a;
b.get();
System.out.println(a instanceof C);
System.out.println(a instanceof D);
}
}
運(yùn)行結(jié)果為
接口D的抽象方法get()
true
true
我們發(fā)現(xiàn)竿裂,從定義結(jié)構(gòu)來講玉吁,A和B兩個(gè)接口沒有任何直接聯(lián)系,但這兩個(gè)接口卻擁有同一個(gè)子類腻异。我們不要被類型和名稱所迷惑进副,因?yàn)閷?shí)例化的是X子類,而這個(gè)類對(duì)象屬于B類對(duì)象悔常,所以以上代碼可行影斑,只不過從代碼的編寫規(guī)范來講,并不是很好机打。
2.對(duì)于子類而言矫户,除了實(shí)現(xiàn)接口外,還可以繼承抽象類残邀。若既要繼承抽象類皆辽,同時(shí)還要實(shí)現(xiàn)接口的話柑蛇,使用一個(gè)語法格式
class 子類 [extends 父類][implements 接口1,接口2]{}
范例
interface E{
public static String MSG = "hello";
public abstract void print();//抽象方法
}
interface F{
public abstract void get();
}
abstract class G{
public abstract void change();
}
class X extends G implements E,F{
@Override
public void print() {
System.out.println("接口E的抽象方法");
}
@Override
public void get() {
System.out.println("接口F的抽象方法");
}
@Override
public void change() {
System.out.println("抽象類G的抽象方法");
}
}
對(duì)于接口驱闷,里面的組成只有抽象方法和全局常量唯蝶,所以很多時(shí)候?yàn)榱藭鴮懞唵危梢圆挥脤憄ublic abstract或者public static final遗嗽。并且粘我,接口中的訪問權(quán)限只有一種:public ,即:定義接口方法和全局常量的時(shí)候就算沒有寫上public,那么最終的訪問權(quán)限也是public痹换,注意不是default征字,注意不是default。以下兩種寫法是完全等價(jià)的:
interface C{
public static final String MSG = "hello";
public abstract void print();
}
等價(jià)于
interface C{
String MSG = "hello";
void print();
}
但是娇豫,這樣會(huì)不會(huì)帶來什么問題呢匙姜?如果子類中的覆寫方法也不是public,我們來看:
interface C{
String MSG = "hello";
void print();
}
class X implements C{
void print(){
System.out.println("接口C的抽象方法");
}
}
public class TestDemo{
public static void main(String[] args){
C c = new X();
c.print();
}
}
這樣運(yùn)行冯痢,系統(tǒng)會(huì)報(bào)錯(cuò)氮昧,這是因?yàn)榻涌谥心J(rèn)是public修飾,若子類中沒有public修飾浦楣,則訪問權(quán)限變嚴(yán)格了袖肥,給子類分配的是更低的訪問權(quán)限。所以振劳,在定義接口的時(shí)候強(qiáng)烈建議在抽象方法前加上public椎组,子類也加上
3.在Java中,一個(gè)抽象類只能繼承一個(gè)抽象類历恐,但一個(gè)接口卻可以使用extends關(guān)鍵字同時(shí)繼承多個(gè)接口(但接口不能繼承抽象類)寸癌。
(1)一個(gè)抽象類只能繼承一個(gè)抽象父類,而接口可以繼承多個(gè)接口弱贼;
(2)一個(gè)子類只能繼承一個(gè)抽象類蒸苇,卻可以實(shí)現(xiàn)多個(gè)接口(Java中,接口的主要功能時(shí)解決單繼承局限問題)
4.從接口的概念來講吮旅,接口只能由抽象方法和全局常量組成溪烤,但是內(nèi)部結(jié)構(gòu)時(shí)不受概念限制的,正如抽象類中可以定義抽象內(nèi)部類一樣鸟辅,在接口中也可以定義普通內(nèi)部類氛什、抽象內(nèi)部類和內(nèi)部接口