Java 接口詳解

1. 什么是接口

(1)在生活中:

接口泛指實體把自己提供給外界的一種抽象化物(可以為另一實體)税手,用以由內(nèi)部操作分離出外部溝通方法雅镊,使其能被內(nèi)部修改而不影響外界其他實體與其交互的方式。

人類與電腦等信息機器或人類與程序之間的接口稱為用戶界面捺信。電腦等信息機器硬件組件間的接口叫硬件接口酌媒。電腦等信息機器軟件組件間的接口叫軟件接口。

在計算機中迄靠,接口是計算機系統(tǒng)中兩個獨立的部件進行信息交換的共享邊界秒咨。這種交換可以發(fā)生在計算機軟、硬件掌挚,外部設備或進行操作的人之間雨席,也可以是它們的結(jié)合。

(2)在Java中:
  • 接口是interface吠式,相當于抽象類陡厘,在繼承關系中充當父類的角色,在接口中通過定義抽象方法來指定規(guī)范特占,子類去實現(xiàn)接口糙置,要實現(xiàn)接口中的所有抽象方法。

2.接口有什么作用

在Java中是目,類是單繼承的谤饭,怎么才能讓類多繼承呢?

家里房檐上的那只燕子是會飛的懊纳,天上的那架飛機也是會飛的揉抵,他們有相同的行為,但是他們是毫不相關的兩個子類嗤疯,是否需要讓讓多個子類繼承同一個抽象類冤今?

此時,可以通過接口茂缚,定義一個飛的接口戏罢,燕子能實現(xiàn),飛機也能實現(xiàn)阱佛,實現(xiàn)了相同的接口帖汞。

所以接口解決的問題是

  1. 多繼承
  2. 不同子類實現(xiàn)相同的行為

3.定義和實現(xiàn)一個簡單的接口

接口的定義與類的定義是相似的。

public interface 接口名 {
    //接口成員
}
  • 和類不同的是凑术,定義接口用的是interface修飾符
  • 接口的訪問權限是public和默認權限翩蘸,與類的訪問權限類似
  • 一個接口可以繼承其他父接口。它將繼承父接口中聲明的常量和抽象方法

接口實現(xiàn)語法格式

class 類 implements 接口 {
    重寫接口中方法
} 

實現(xiàn)一個簡單的接口

interface IShout extends IFly{

class Rabbit implements IShout{
    //實現(xiàn)shout()方法
    @Override
    public void shout() {
        
    }
    //實現(xiàn)fly()方法
    @Override
    public void fly() {
        
    }
}

實現(xiàn)接口就是遵循接口的規(guī)范

  • 實現(xiàn)接口使用implements關鍵字
  • 一個類可以實現(xiàn)多個接口淮逊,各接口之間用逗號分隔
  • 實現(xiàn)接口的類必須實現(xiàn)接口定義的所有抽象方法催首,即使類中不使用某個抽象方法也必須實現(xiàn)它,通承古簦空方法體實現(xiàn)子類不需要的抽象方法郎任,如果抽象方法有返回值,可使用默認值备籽。
  • 接口的實現(xiàn)類允許包含普通方法
  • 在實現(xiàn)抽象方法時需要指定public權限舶治,否則會產(chǎn)生編譯錯誤
  • 接口和類分井,抽象類是同一層次的概念,命名規(guī)則相同

接口的成員特點:

  • 成員變量:只能是常量 默認有修飾符:public static final
  • 構造方法:接口沒有構造方法霉猛,因為接口主要是對行為進行抽象的尺锚,是沒有具體存在。
  • 成員方法: 只能是抽象方法 默認修飾符:public abstract

4. 接口的多實現(xiàn)

接口最重要的體現(xiàn):解決多繼承的弊端惜浅。將多繼承這種機制在java中通過多實現(xiàn)完成了瘫辩。

interface Fu1
{
    void show1();//接口定義規(guī)范show1()
}
interface Fu2
{
    void show2();//接口定義規(guī)范show2()
}
class Zi implements Fu1,Fu2// 多實現(xiàn)。同時實現(xiàn)多個接口坛悉。
{
    public void show1(){}//子類實現(xiàn)show1()規(guī)范
    public void show2(){}//子類實現(xiàn)show2()規(guī)范
}

多繼承的弊端是什么伐厌?

  • 在多繼承時,當父類之中有相同的功能時裸影,子類調(diào)用這個功能會產(chǎn)生不確定性
  • 核心問題在于父類之中有主方法體挣轨,導致了調(diào)用運行的時候不確定運行哪個主體。

多實現(xiàn)是怎么解決的這個弊端轩猩?

  • 在接口之中的功能都是沒有方法體的刃唐,由子類來實現(xiàn)。

5.類繼承類的同時也可以實現(xiàn)接口

在子類繼承父類的同時界轩,也可以實現(xiàn)接口画饥,方法如下

class Father{
    public void getOne(){ }
} 
interface Inter {
    void getTwo();
}
interface Outer{
    void getThree();
}

class Son extends Father implements Inter,Outer{

    @Override
    public void getTwo() {
        
    }

    @Override
    public void getThree() {

    }
}

接口的出現(xiàn)避免了單繼承的局限性。父類中定義的事物的基本功能浊猾。接口中定義的事物的擴展功能抖甘。

  • 接口和類之間可以通過實現(xiàn)(implements)產(chǎn)生關系
  • 類與類之間可以通過繼承(extends)產(chǎn)生關系
  • 當一個類已經(jīng)繼承了一個父類,它又需要擴展額外的功能葫慎,這時接口就派上用場了衔彻。
  • 子類通過繼承父類擴展功能,通過繼承擴展的功能都是子類應該具備的基礎功能偷办。如果子類想要繼續(xù)擴展其他類中的功能呢艰额?這時通過實現(xiàn)接口來完成。

6. 接口和接口之間的繼承

接口和接口之間也是可以繼承的

public interface IFu1 {
    void show1();
}
public interface IFu2 {
    void show2();
}
public interface IZi extends IFu1,IFu2{
    void show3();//接口繼承了IFu1,IFu2兩個父類接口
}
public class Demo implements IZi{
    @Override
    public void show3() {
    }
    @Override
    public void show1() {
    }
    @Override
    public void show2() {
    }
}
  • 接口與接口之間的繼承是可以多繼承的

  • 在開發(fā)中如果多個接口中存在相同方法椒涯,這時若有個類實現(xiàn)了這些接口柄沮,那么就要實現(xiàn)接口中的方法,由于接口中的方法是抽象方法废岂,子類實現(xiàn)后也不會發(fā)生調(diào)用的不確定性祖搓。

7. 接口的規(guī)定

  1. 接口中可以定義變量,但是變量必須有固定的修飾符修飾湖苞,public static final 所以接口中的變量也稱之為常量拯欧,其值不能改變。
  2. 接口中可以定義方法财骨,方法也有固定的修飾符镐作,public abstract(寫代碼時可以省略藏姐,默認有public abstract)
  3. 接口不可以new,即不可以實例化该贾。
  4. 子類必須覆蓋掉接口中所有的抽象方法后包各,子類才可以實例化。否則子類是一個抽象類靶庙。
  5. 接口不能繼承類,接口可以繼承接口
  6. 接口沒有最高層娃属,類的最高層是Object
  7. 接口中不允許有普通方法六荒,所以接口中的方法都是抽象(jdk1.8后可以有default方法和static方法)
  8. 接口不是類,所以沒有構造

8. jdk1.8接口的新特性

在1.8版本之后矾端,接口內(nèi)不只可以定義抽象方法掏击,還能定義static以及default修飾的實例方法。

static方法:

public interface IDemo {
    public static void demo1(){
        System.out.println("static方法...");
    }
}
    public static void main(String[] args) {
        IDemo.demo1();//直接使用接口名.方法名使用
    }
}

default方法

public interface IDemo {
    default void demo2(){
        System.out.println("default方法......");
    }
}
public class Demo implements IDemo{

    public static void main(String[] args) {
        Demo demo = new Demo();
        demo.demo2();
    }
}
public class Demo implements IDemo{

    @Override
    public void demo2() {//子類可以直接使用秩铆,也可以重寫
        System.out.println("重寫后的default方法...");
    }
    public static void main(String[] args) {
        Demo demo = new Demo();
        demo.demo2();
    }
}

9.面向接口編程

接口有多種用法:

  1. 接口可以作為子類的實現(xiàn)
  2. 接口可以作為類的屬性
  3. 接口可以作為方法的參數(shù)
  4. 接口可以作為方法的返回值

(1) 接口可以作為子類的實現(xiàn)

public interface IFu1 {
    void show1();
}
public class Demo1 implements IFu1{
    @Override
    public void show1() {
        System.out.println("demo1 is running...");
    }
}

(2) 接口作為類的屬性

創(chuàng)建接口

public interface IFu1 {
    void show1();
}

創(chuàng)建兩個子類實現(xiàn)接口

public class Demo1 implements IFu1{
    @Override
    public void show1() {
        System.out.println("demo1 is running...");
    }
}
public class Demo2 implements IFu1{
    @Override
    public void show1() {
        System.out.println("demo2 is running ...");
    }
}

將接口作為屬性

public class Demo {
    private IFu1 iFu1;


    public IFu1 getiFu1() {
        return iFu1;
    }

    public void setiFu1(IFu1 iFu1) {
        this.iFu1 = iFu1;
    }
}

使用接口的屬性

public class Test {
    public static void main(String[] args) {
        Demo demo = new Demo();
        IFu1 iFu1 = new Demo1();//創(chuàng)建IFu1接口的子類Demo1對象
        demo.setiFu1(iFu1);//將IFu1接口的子類Demo1對象傳入Demo的屬性iFu1
        demo.getiFu1().show1();//調(diào)用的是Demo1的show1()
    }
}

結(jié)果:demo1 is running...

(3)接口可以作為方法的參數(shù)

public interface IFu1 {
    void show1();
}
public class Demo1 implements IFu1{
    @Override
    public void show1() {
        System.out.println("demo1 is running...");
    }
}
public class Demo2 implements IFu1{

    @Override
    public void show1() {
        System.out.println("demo2 is running ...");
    }
}
public class Demo {
   public  void testInterface(IFu1 iFu1){
       iFu1.show1();
   }//接口作為方法的參數(shù)
}
public class Test {
    public static void main(String[] args) {
        Demo demo = new Demo();
        IFu1 iFu1 = new Demo1();//創(chuàng)建IFu1接口的子類Demo1對象
        demo.testInterface(iFu1);//使用的Demo1的方法
        
        iFu1 = new Demo2();
        demo.testInterface(iFu1);//使用的Demo2的方法
    }
}

結(jié)果為:

demo1 is running...
demo2 is running ...

(4)接口可以作為方法的返回值

public interface IFu1 {
    void show1();
}
public class Demo1 implements IFu1{
    @Override
    public void show1() {
        System.out.println("demo1 is running...");
    }
}
public class Demo {
   public  IFu1 testInterface(String type){
       IFu1 iFu1 = null;//定義接口對象
       if(type==null){
           throw new RuntimeException("非法參數(shù)異常");
       }
       if(type.equalsIgnoreCase("demo1")){
           return new Demo1();
       }else if(type.equalsIgnoreCase("demo2")){
           return new Demo2();
       }else{
           return null;
       }
   }//接口作為方法的返回值
}
public class Test {
    public static void main(String[] args) {
        Demo demo = new Demo();
        IFu1 iFu1 = demo.testInterface("demo1");
        iFu1 = demo.testInterface("demo2");
    }
}
  • 接口作為屬性砚亭、方法的參數(shù)、方法返回值時殴玛,可以返回任何實現(xiàn)了該接口的子類實例捅膘,接口對象調(diào)用方法時,調(diào)用的是傳入子類的方法滚粟。
  • 這種設計的原理是里氏替換原則寻仗,即父類引用指向子類實例。

面向接口編程的核心是:父類引用指向子類對象凡壤,換個角度來理解就是凡是使用父類的地方都可以使用子類替換父類署尤。

面向接口編程的好處

  • 降低了程序的耦合性,其能夠最大限度的解耦亚侠,所謂解耦既是解耦合的意思曹体,它和耦合相對。耦合就是聯(lián)系硝烂,耦合越強箕别,聯(lián)系越緊密。在程序中緊密的聯(lián)系并不是一件好的事情滞谢,因為兩種事物之間聯(lián)系越緊密究孕,你更換其中之一的難度就越大,擴展功能和debug的難度也就越大爹凹。
  • 易擴展厨诸,我們知道程序設計的原則是對修改關閉,對新增開放.面向接口編程擴展功能只需要創(chuàng)建新實現(xiàn)類重寫接口方法進行升級擴展就可以,達到了在不修改源碼的基礎上擴展的目的.
  • 易維護
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市禾酱,隨后出現(xiàn)的幾起案子微酬,更是在濱河造成了極大的恐慌绘趋,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颗管,死亡現(xiàn)場離奇詭異陷遮,居然都是意外死亡页响,警方通過查閱死者的電腦和手機慧域,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谬哀,“玉大人比吭,你說我怎么就攤上這事绽族。” “怎么了衩藤?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵吧慢,是天一觀的道長。 經(jīng)常有香客問我赏表,道長检诗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任瓢剿,我火速辦了婚禮逢慌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘间狂。我一直安慰自己涕癣,他們只是感情好,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布前标。 她就那樣靜靜地躺著坠韩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪炼列。 梳的紋絲不亂的頭發(fā)上只搁,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天,我揣著相機與錄音俭尖,去河邊找鬼氢惋。 笑死,一個胖子當著我的面吹牛稽犁,可吹牛的內(nèi)容都是我干的焰望。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼已亥,長吁一口氣:“原來是場噩夢啊……” “哼熊赖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起虑椎,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤震鹉,失蹤者是張志新(化名)和其女友劉穎俱笛,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體传趾,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡迎膜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了浆兰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片磕仅。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖簸呈,靈堂內(nèi)的尸體忽然破棺而出榕订,到底是詐尸還是另有隱情,我是刑警寧澤蝶棋,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站忽妒,受9級特大地震影響玩裙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜段直,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一吃溅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸯檬,春花似錦决侈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至功茴,卻和暖如春庐冯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背坎穿。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工展父, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人玲昧。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓栖茉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親孵延。 傳聞我的和親對象是個殘疾皇子吕漂,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 申明:非原創(chuàng),轉(zhuǎn)載自 Java接口 詳解(一)Java接口 詳解(二) 一尘应、基本概念 接口(Interface)痰娱,...
    愛敲代碼的王小帥閱讀 587評論 1 3
  • Java 接口 接口(英文:Interface)弃榨,在JAVA編程語言中是一個抽象類型,是抽象方法的集合梨睁,接口通常以...
    邱獻旭閱讀 264評論 0 1
  • 《abstract關鍵字》 —————————— 抽象類:含有抽象方法的類鲸睛。抽象類必須也要用abstract關鍵字...
    好大一顆星閱讀 760評論 0 0
  • 1、抽象類:如果這個類里面的方法有一個是抽象的坡贺,那么這個類必須是抽象的官辈。抽象類中的方法,子類必須實現(xiàn)遍坟。抽象類中可以...
    AsgoodAswater閱讀 303評論 0 0
  • 人生像攀登一座山拳亿,而找尋出路,卻是一種學習的過程愿伴,我們應當在這過程中肺魁,學習穩(wěn)定、冷靜隔节,學習如何從慌亂中找到生機鹅经。—...
    編程自習室閱讀 690評論 0 2