面試官:小伙子刨沦,你給我說一下Java接口新特性及抽象類與接口的區(qū)別吧

前言

接口诗宣,是Java語言中一種引用數(shù)據(jù)類型,是方法的集合想诅,如果說類的內(nèi)部封裝了成員變量召庞、構造方法和成員方法,那么接口的內(nèi)部主要就是封裝了方法侧蘸,包含抽象方法(JDK 7及以前)裁眯,默認方法和靜態(tài)方法(JDK 8),私有方法(JDK 9)讳癌。

在Java中穿稳,接口表示一種規(guī)范/約束,要求實現(xiàn)者必須遵循該規(guī)范:用來約束使用者應該怎么做晌坤。繼承是一個"是不是"的關系逢艘,而接口實現(xiàn)則是 "能不能"的關系,是行為的抽象骤菠。

接口的定義,它與定義類方式相似商乎,但是使用 interface 關鍵字央拖。接口也是定義在 .java 文件中的鹉戚,它也會被編譯成 .class文件遏餐,但一定要明確它并不是類,而是另外一種引用數(shù)據(jù)類型粹庞。

class 類名.java --> .class 文件

interface 接口名.java --> .class 文件

接口的使用黔攒,它不能創(chuàng)建對象旅掂,但是可以被實現(xiàn)(implements 商虐,類似于被繼承)秘车。一個實現(xiàn)接口的類(可以看做是接口的子類),需要實現(xiàn)接口中所有的抽象方法伤溉,創(chuàng)建該類對象乱顾,就可以調用方法了,否則它必須聲明為抽象類。

定義格式

接口只能使用 public abstract 關鍵字修飾震檩,abstract 一般不寫。

public interface 接口名稱 {
    // 常量
    // 抽象方法   實現(xiàn)類必須全部重寫
    // 默認方法   實現(xiàn)類可以重寫,也可以直接使用
    // 靜態(tài)方法   接口名直接調用
    // 私有方法   本接口中,自己使用
}

public 關鍵字是常量、抽象方法徐紧、默認方法并级、靜態(tài)方法的默認修飾符呀潭,可以省略舰蟆。

常量

接口中塌鸯,無法定義成員變量涨颜,但是可以定義常量庭瑰,其值不可以改變,默認使用 public static final 修飾穷吮,修飾符可省略

定義接口:

public interface LiveAble {
   int NUM0; // 錯誤酒来,必須賦值  
   int NUM1 =10; // 正確堰汉,省去了默認修飾符 public static final
   public static final int NUM2= 100; // 正確戳葵,完整寫法
}

定義測試類:

public class InterfaceDemo {
   public static void main(String[] args) {
        System.out.println(Live.NUM1);
        System.out.println(Live.NUM2);
    }
}
輸出結果:
10
100

抽象方法

抽象方法:默認使用 public abstract 修飾,可以省略。該方法供子類實現(xiàn)使用擅笔。

代碼如下:

public interface InterfaceName {
     public abstract void method();
}

默認方法和靜態(tài)方法

默認方法:使用 public default 修飾绿店,default 不可省略惕它,有方法體,供子類調用或者子類重寫废登。

靜態(tài)方法:使用 public static 修飾,static 不可省略郁惜,有方法體堡距,供接口直接調用。

代碼如下:

public interface InterfaceName {
     public default void method() {
        // 執(zhí)行語句
    }
     public static void method2() {
        // 執(zhí)行語句    
    }
}

私有方法

私有方法:使用 private 修飾兆蕉,不可省略羽戒,供接口中的默認方法或者靜態(tài)方法調用。
代碼如下:

public interface InterfaceName {
    private void method() {
        // 執(zhí)行語句
    }
}

實現(xiàn)的概述

類與接口的關系為實現(xiàn)關系虎韵,即類實現(xiàn)接口易稠,該類可以稱為接口的實現(xiàn)類,也可以稱為接口的子類包蓝。實現(xiàn)的動作類似繼承驶社,格式相仿,只是關鍵字不同测萎,實現(xiàn)使用 implements 關鍵字亡电。

非抽象子類實現(xiàn)接口:

  1. 必須重寫接口中所有抽象方法。
  2. 繼承了接口的默認方法硅瞧,既可以直接調用份乒,也可以重寫。

實現(xiàn)格式:

class 類名 implements 接口名 {
    // 重寫接口中抽象方法【必須】
    // 重寫接口中默認方法【可選】
} 

抽象方法的使用

必須全部實現(xiàn)腕唧,代碼如下:

定義接口:

public interface LiveAble {
    // 定義抽象方法
    public abstract void eat();
    public abstract void sleep();
}

定義實現(xiàn)類:

public class Animal implements LiveAble {

    @Override
    public void eat() {
        System.out.println("吃東西");
    }

    @Override
    public void sleep() {
        System.out.println("晚上睡覺");
    }
}

定義測試類:

public class InterfaceDemo {
    public static void main(String[] args) {
        // 創(chuàng)建子類對象  
        Animal a = new Animal();
        // 調用實現(xiàn)后的方法
        a.eat();
        a.sleep();
    }
}
輸出結果:
吃東西
晚上睡

默認方法的使用

可以繼承或辖,可以重寫,二選一枣接,但是只能通過實現(xiàn)類的對象來調用颂暇。

  1. 繼承默認方法,代碼如下:

定義接口:

public interface LiveAble {
    public default void fly(){
        System.out.println("天上飛");
    }
}

定義實現(xiàn)類:

public class Animal implements LiveAble {
    // 繼承月腋,什么都不用寫蟀架,直接調用
}

定義測試類:

public class InterfaceDemo {
    public static void main(String[] args) {
        // 創(chuàng)建子類對象  
        Animal a = new Animal();
        // 調用默認方法
        a.fly();
    }
}
輸出結果:
天上飛

  1. 重寫默認方法,代碼如下:

定義接口:

public interface LiveAble {
    public default void fly(){
        System.out.println("天上飛");
    }
}

定義實現(xiàn)類:

public class Animal implements LiveAble {
    @Override
    public void fly() {
        System.out.println("自由自在的飛");
    }
}

定義測試類:

public class InterfaceDemo {
    public static void main(String[] args) {
        // 創(chuàng)建子類對象  
        Animal a = new Animal();
        // 調用重寫方法
        a.fly();
    }
}
輸出結果:
自由自在的飛

靜態(tài)方法的使用

接口中的靜態(tài)方法只能使用接口名調用榆骚,實現(xiàn)類不能重寫片拍,不可以通過實現(xiàn)類的類名或者實現(xiàn)類的對象調用,代碼如下:

定義接口:

public interface LiveAble {
    public static void run(){
        System.out.println("跑起來~~~");
    }
}

定義實現(xiàn)類:

public class Animal implements LiveAble {
    // 無法重寫靜態(tài)方法
}

定義測試類:

public class InterfaceDemo {
    public static void main(String[] args) {
        // Animal.run(); // 【錯誤】無法繼承方法妓肢,也無法調用
        LiveAble.run(); // 
    }
}
輸出結果:
跑起來~~~

私有方法的使用

  • 私有非靜態(tài)方法:只有默認方法可以調用捌省;解決多個默認方法之間重復代碼問題
  • 私有靜態(tài)方法:默認方法和靜態(tài)方法可以調用,解決多個靜態(tài)方法之間重復代碼問題

因為是私有的碉钠,所以子接口和實現(xiàn)類不能覆蓋重寫纲缓。

如果一個接口中有多個默認方法卷拘,并且方法中有重復的內(nèi)容,那么可以抽取出來祝高,封裝到私有方法中栗弟,供默認方法去調用。從設計的角度講工闺,私有的方法是對默認方法和靜態(tài)方法的輔助乍赫。

定義接口:

public interface LiveAble {
    default void func(){
        func1();
        LiveAble.func2();
    }
    private void func1(){
        System.out.println("func1~~~");
    }
    private static void func2(){
        System.out.println("func2~~~");
    }
}

接口的多實現(xiàn)

之前學過,在繼承體系中陆蟆,一個類只能繼承一個父類雷厂。而對于接口而言,一個類是可以實現(xiàn)多個接口的叠殷,這叫做接口的多實現(xiàn)改鲫。并且,一個類能繼承一個父類林束,同時實現(xiàn)多個接口像棘。

實現(xiàn)格式:

修飾符 class 類名 [extends 父類名] implements 接口名1, 接口名2, 接口名3... {
    // 重寫接口中抽象方法【必須】
    // 重寫接口中默認方法【不重名時可選】
} 

抽象方法

接口中,有多個抽象方法時诊县,實現(xiàn)類必須重寫所有的抽象方法讲弄。如果多個接口的抽象方法有重名的,只需要重寫一次依痊。代碼如下:

定義多個接口:

interface A {
    public abstract void showA();
    public abstract void show();
}

interface B {
    public abstract void showB();
    public abstract void show();
}

定義實現(xiàn)類:

public class C implements A, B{
    @Override
    public void showA() {
        System.out.println("showA");
    }

    @Override
    public void showB() {
        System.out.println("showB");
    }

    @Override
    public void show() {
        System.out.println("show");
    }
}

默認方法

接口中避除,有多個默認方法時,實現(xiàn)類都可繼承使用胸嘁。如果多個接口的默認方法有重名的瓶摆,必須重寫一次。代碼如下:

定義多個接口:

interface A {
    public default void methodA(){}
    public default void method(){}
}

interface B {
    public default void methodB(){}
    public default void method(){}
}

定義實現(xiàn)類:

public class C implements A,B{
    @Override
    public void method() {
        System.out.println("method");
    }
}

靜態(tài)方法

多個接口中性宏,存在同名的靜態(tài)方法并不會沖突群井,原因是只能通過各自接口名訪問靜態(tài)方法。

public interface MyInterface {
    public static void inter(){
        system.out.println("接口靜態(tài)方法");
    }
}

public class Test {
    public static void main(String[] args){
        //接口名直接調用
        MyInterface.inter();
    }
}

方法重名時的優(yōu)先級問題

當一個類毫胜,既繼承一個父類书斜,又實現(xiàn)若干個接口時,若父類中的成員方法與接口中的默認方法重名且子類中未重寫酵使,子類就近選擇執(zhí)行父類的成員方法荐吉。代碼如下:
定義接口:

interface A {
    public default void methodA() {
        System.out.println("AAAAAAAAAAAA");
    }
}

定義父類:

class B {
    public void methodA() {
        System.out.println("BBBBBBBBBBBB");
    }
}

定義子類:

class C extends B implements A {
    // 未重寫methodA方法  
}

定義測試類:

public class Test {
    public static void main(String[] args) {
        C c = new C();
        c.methodA();
    }
}
輸出結果:
BBBBBBBBBBBB

接口的多繼承

一個接口能繼承另一個或者多個接口,這和類之間的繼承比較相似口渔。接口的繼承使用 extends 關鍵字样屠,子接口繼承父接口的方法。如果父接口中的默認方法有重名的,那么子接口需要重寫一次痪欲。代碼如下:

定義父接口:

interface A {
    public default void method(){
        System.out.println("AAAAAAAAAAAAAAAAAAA");
    }
}

interface B {
    public default void method(){
        System.out.println("BBBBBBBBBBBBBBBBBBB");
    }
}

定義子接口:

interface C extends A,B {
    @Override
    public default void method() {
        System.out.println("CCCCCCCCCCCCCCCCCCC");
    }
}

子接口重寫默認方法時悦穿,default關鍵字必須保留。
子類重寫默認方法時业踢,default關鍵字不可以保留栗柒。

接口解決了其他語言中多繼承的弊端,將多繼承這種機制在java中通過多實現(xiàn)來完成:

  1. 多繼承的弊端:當多個父類中有相同功能時陨亡,子類調用會產(chǎn)生不確定性傍衡。核心原因就是在于多繼承父類中方法有主體,而導致調用運行時负蠕,不確定運行哪個主體內(nèi)容。

  2. 為什么多實現(xiàn)能解決這種沖突倦畅?:因為接口中的功能都沒有方法體遮糖,需要由子類來明確。

接口的其他特點

接口沒有構造器叠赐、代碼塊欲账,因為接口中沒有類變量和實例變量需要初始化,只有常量

接口不能直接實例化創(chuàng)建對象芭概,因為沒有構造器

抽象類和接口的區(qū)別

通過實例進行分析和代碼演示抽象類和接口的用法赛不。

1、舉例:

? 犬:

? 行為:

? 吼叫罢洲;

? 吃飯踢故;

? 緝毒犬:

? 行為:

? 吼叫;

? 吃飯惹苗;

? 緝毒殿较;

2、思考:

? 由于犬分為很多種類桩蓉,他們吼叫和吃飯的方式不一定相同淋纲,在描述的時候不能具體化私恬,也就是吼叫和吃飯的行為不能明確兄猩。當描述行為時,行為的具體動作不能明確操漠,這時业汰,可以將這個行為寫成抽象行為伙窃,那么這個類也就是抽象類。

? 可是當緝毒犬有其他額外功能時蔬胯,而這個功能并不在這個事物的體系中对供。這時可以讓緝毒犬具備犬科自身特點的同時也有其他額外功能,可以將這個額外功能到定義接口中,實現(xiàn)緝毒功能的既可以緝毒警察产场,也可以是緝毒犬鹅髓。

interface 緝毒 {
    public abstract void 緝毒();
}

//定義犬科的共性功能
abstract class 犬科{
    public abstract void 吃飯();
    public abstract void 吼叫();
}
// 緝毒犬屬于犬科一種,讓其繼承犬科京景,獲取到犬科的特性窿冯,
//由于緝毒犬具有緝毒功能,那么它只要實現(xiàn)緝毒接口即可确徙,這樣即保證緝毒犬具備犬科的特性醒串,也擁有了緝毒的功能
class 緝毒犬 extends 犬科 implements 緝毒 {
    public void 緝毒() {
    }
    void 吃飯() {
    }
    void 吼叫() {
    }
}

3、通過上面的例子總結接口和抽象類的區(qū)別:

相同點:

都位于繼承的頂端鄙皇,用于被其他類實現(xiàn)或繼承芜赌;

都不能直接實例化對象;

都包含抽象方法伴逸,其子類都必須實現(xiàn)這些抽象方法缠沈;

區(qū)別:

抽象類中可以變量、常量错蝴,抽象方法洲愤,非抽象方法,構造方法顷锰;接口中可以有常量柬赐,抽象方法( JDK8新增:默認方法,靜態(tài)方法官紫;JDK9新增:私有方法)

一個類只能繼承一個直接父類(可能是抽象類)肛宋,卻可以實現(xiàn)多個接口(接口彌補了Java的單繼承的局限性)

抽象類為繼承體系中的共性內(nèi)容,接口為繼承體系中的擴展功能

  • 成員區(qū)別

    • 抽象類
      • 變量万矾,常量悼吱;抽象方法,非抽象方法良狈,構造方法
    • 接口
      • 常量后添;抽象方法( JDK8:默認方法,靜態(tài)方法薪丁;JDK9:私有方法)
  • 關系區(qū)別

    • 類與類
      • 繼承遇西,單繼承
    • 類與接口
      • 實現(xiàn),可以單實現(xiàn)严嗜,也可以多實現(xiàn)
    • 接口與接口
      • 繼承粱檀,單繼承,多繼承
  • 設計理念區(qū)別

    • 抽象類

      • 對類抽象漫玄,包括屬性茄蚯、行為
    • 接口

      • 對行為抽象压彭,主要是行為

最后

感謝你看到這里,看完有什么的不懂的可以在評論區(qū)問我渗常,覺得文章對你有幫助的話記得給我點個贊壮不,每天都會分享java相關技術文章或行業(yè)資訊,歡迎大家關注和轉發(fā)文章皱碘!

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末询一,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子癌椿,更是在濱河造成了極大的恐慌健蕊,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件踢俄,死亡現(xiàn)場離奇詭異缩功,居然都是意外死亡,警方通過查閱死者的電腦和手機都办,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門掂之,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人脆丁,你說我怎么就攤上這事《ⅲ” “怎么了槽卫?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長胰蝠。 經(jīng)常有香客問我歼培,道長,這世上最難降的妖魔是什么茸塞? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任躲庄,我火速辦了婚禮,結果婚禮上钾虐,老公的妹妹穿的比我還像新娘噪窘。我一直安慰自己,他們只是感情好效扫,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布倔监。 她就那樣靜靜地躺著,像睡著了一般菌仁。 火紅的嫁衣襯著肌膚如雪浩习。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天济丘,我揣著相機與錄音谱秽,去河邊找鬼。 笑死,一個胖子當著我的面吹牛疟赊,可吹牛的內(nèi)容都是我干的郊供。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼听绳,長吁一口氣:“原來是場噩夢啊……” “哼颂碘!你這毒婦竟也來了?” 一聲冷哼從身側響起椅挣,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤头岔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鼠证,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體峡竣,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年量九,在試婚紗的時候發(fā)現(xiàn)自己被綠了适掰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡荠列,死狀恐怖类浪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情肌似,我是刑警寧澤费就,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站川队,受9級特大地震影響力细,放射性物質發(fā)生泄漏。R本人自食惡果不足惜固额,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一眠蚂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧斗躏,春花似錦逝慧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至迈套,卻和暖如春捐祠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背桑李。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工踱蛀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留窿给,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓率拒,卻偏偏與公主長得像崩泡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子猬膨,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348