91精品国产手机在线-白筒袜嫩萝双腿之间乳白液体-青青操手机在线视频观看-日本中文字幕人妻日韩-日韩精品在线观看视频网站-天堂资源中文最新版在线一区-欧美专区一区二区三区-国产综合亚洲欧美在线-国产精品久久久久久福利69堂

一文讀懂java接口的特點 java接口的作用和意義例子

0. 前言在我自己早期學(xué)習(xí)編程的時候 , 對接口存在的意義實在困惑 , 我自己亂寫代碼的時候基本上不可能意識到需要去寫接口 , 不知道接口到底有什么用 , 為什么要定義接口 , 感覺定義接口只是 提前做了個多余的工作 。
這里我先拋出一個形象的解釋 , 大家?guī)е@個解釋結(jié)合全文來理解接口存在的意義是什么:
我們把電腦主板上的內(nèi)存插槽 , 顯卡插槽等類比為接口 , 為什么在主板上搞這么多插槽呢?多浪費機箱空間啊?直接用電烙鐵把顯卡和內(nèi)存的引腳一根一根焊到主板上不就得了(手動滑稽) 。估計讀到這里大伙兒心里也大概明白了接口的大致作用 , 焊死了后 , 如果你焊錯位置了或者拆電腦的時候 , 就需要使用電烙鐵進行拆裝 , 多愚蠢哦 。
全文脈絡(luò)思維導(dǎo)圖如下:

一文讀懂java接口的特點 java接口的作用和意義例子

文章插圖
1. 什么是抽象類在講解接口之前 , 抽象類是繞不過去的一個概念 , 接口可以認為是一個比抽象類還要抽象的類 。
什么是抽象類?「包含一個或多個抽象方法的類就是抽象類 , 抽象方法即沒有方法體的方法」 , 抽象方法和抽象類都必須聲明為 abstract 。例如:
// 抽象類public abstract class Person {// 抽象方法 public abstract String getDescription();}切記!「除了抽象方法之外 , 抽象類還可以包含具體數(shù)據(jù)和具體方法」 。例如 ,  抽象類 Person 還保存著姓名和一個返回姓名的具體方法:
public abstract class Person{private String name;public Person(String name){this.name = name ;}public abstract String getDescription();public String getName(){return name;}}
?
許多程序員都會「錯誤」地認為 , 在抽象類中不能包含具體方法 。其實這也是接口和抽象類的不同之處 , 接口中是不能包含具體方法的 。
?
「抽象類不能被實例化」 。也就是說 , 如果將一個類聲明為 abstract, 就不能創(chuàng)建這個類的對象 。
new Person("Jack"); // Error可以定義一個抽象類的對象變量 ,  但是它只能引用非抽象子類的對象 。假設(shè) Student 類是 Person 的非抽象子類:
Person p = new Student("Jack"); // Right所謂非抽象子類就是說 , 如果創(chuàng)建一個繼承抽象類的子類并為之創(chuàng)建對象 , 那么就「必須為父類的所有抽象方法提供方法定義」 。如果不這么做(可以選擇不做) , 子類仍然是一個抽象類 , 編譯器會強制我們?yōu)樾骂惣由?abstract 關(guān)鍵字 。
下面定義擴展抽象類 Person 的具體子類 Student:
public class Student extends Person {private String major;public Student(String name, String major) {super(name);this.major = major;}@Overridepublic String getDescription(){ // 實現(xiàn)父類抽象方法return "a student majoring in " + major;} } 在 Student 類中實現(xiàn)了父類中的抽象方法 getDescription。因此 , 「在 Student類中的全部方法都是非抽象的 ,  這個類不再是抽象類」 。
調(diào)用如下:
Person p = new Student("Jack","Computer Science");p.getDescription();由于不能構(gòu)造抽象類 Person的對象 ,  所以變量 p 永遠不會引用 Person 對象 ,  而是引用諸如 Student這樣的具體子類對象 ,  而這些對象中都重寫了 getDescription方法 。
2. 什么是接口接口的本質(zhì)其實也是一個類 , 而且是一個比抽象類還要抽象的類 。怎么說呢?抽象類是能夠包含具體方法的 , 而接口杜絕了這個可能性 , 「在 Java 8 之前 , 接口非常純粹 , 只能包含抽象方法 , 也就是沒有方法體的方法」 。而 Java 8 中接口出現(xiàn)了些許的變化 , 開始允許接口包含默認方法和靜態(tài)方法 , 這個下文會講解 。
Java 使用關(guān)鍵字 interface 而不是 class 來創(chuàng)建接口 。和類一樣 , 通常我們會在關(guān)鍵字 interface 前加上 public 關(guān)鍵字 , 否則接口只有包訪問權(quán)限 , 只能在接口相同的包下才能使用它 。
public interface Concept {void idea1();void idea2();}同樣的 , 接口中既然存在抽象方法 , 那么他就需要被擴展(繼承) 。使用 implements 關(guān)鍵字使一個類擴展某個特定接口(或一組接口) , 通俗來說:接口只是外形 , 現(xiàn)在這個擴展子類要說明它是如何工作的 。
class Implementation implements Concept {@Overridepublic void idea1() {System.out.println("idea1");}@Overridepublic void idea2() {System.out.println("idea2");}}這里需要注意的是 , 你可以選擇顯式地聲明接口中的方法為 public , 但是「即使你不這么做 , 它們也是 public 的」 。所以當(dāng)實現(xiàn)一個接口時 , 來自接口中的方法必須被定義為 public 。否則 , 它們只有包訪問權(quán)限 , 這樣在被繼承時 , 它們的可訪問權(quán)限就被降低了 , 這是 Java 編譯器所不允許的 。
另外 , 接口中是允許出現(xiàn)常量的 , 與接口中的方法都自動地被設(shè)置為 public—樣 , 「接口中的域?qū)⒈蛔詣颖辉O(shè)置為 public static final 類型」 , 例如:
public interface Concept { void idea1(); // public void idea1();// 靜態(tài)屬性 double item = 95; // a public static final constant}
?
可以將接口方法標記為 public , 將域標記為 public static final 。有些程序員出于習(xí)慣或提高清晰度的考慮 ,  愿意這樣做 。但 Java 語言規(guī)范卻「建議不要書寫這些多余的關(guān)鍵字」 。
?
3. 接口的特性接口和類其中不同的一點就是 , 我們「無法像類一樣使用 new 運算符來實例化一個接口」:
x = new Concept(. . .); // ERROR原因也很簡單 , 接口連具體的構(gòu)造方法都沒有 , 肯定是無法實例化的 。
當(dāng)然 ,  盡管不能構(gòu)造接口的對象 , 聲明接口的變量還是可以的:
Concept x; // OK接口變量必須引用實現(xiàn)了接口的類對象:
x = new Implementation(. . .); // OK provided Implementation implements Concept接下來 ,  如同使用 instanceof 檢查一個對象是否屬于某個特定類一樣 ,  也可以使用 instanceof檢查一個對象是否實現(xiàn)了某個特定的接口:
if(x instanceof Concept){ ...}另外 , 與可以建立類的繼承關(guān)系一樣 , 「接口也可以被繼承」:
public interface Concept1 {void idea1();void idea2();}-------------------------------------------public interface Concept2 extends Concept1{ double idea3();}當(dāng)然 , 讀到這里大家可能依然無法理解 , 既然有了抽象類 , 為什么 Java 程序設(shè)計語言還要不辭辛苦地引入接口這個概念?
很重磅!因為「一個類可以實現(xiàn)多個接口 , 但是一個類只能繼承一個父類」 。正是接口的出現(xiàn)打破了 Java 這種單繼承的局限 , 為定義類的行為提供了極大的靈活性 。
class Implementation implements Concept1, Concept2 // OK有一條實際經(jīng)驗:在合理的范圍內(nèi)盡可能地抽象 。顯然 , 接口比抽象類還要抽象 。因此 , 一般更傾向使用接口而不是抽象類 。
4. Java 8 接口新特性上文提過一嘴 , 「在 Java 8 中 , 允許在接口中增加靜態(tài)方法和默認方法」 。理論上講 , 沒有任何理由認為這是不合法的 , 只是這有違于將接口作為抽象規(guī)范的初衷 。舉個例子:
public interface Concept {// 靜態(tài)方法 public static void get(String name){System.out.println("hello " + name);}// 默認方法default void idea1(){System.out.println("this is idea1");};}用 default 修飾符標記的方法就是默認方法 , 這樣子類就不需要去實現(xiàn)這個方法了 。
不過 , 引入默認方法后 , 就出現(xiàn)了一個「默認方法沖突」的問題 。如果先在一個接口 A 中將一個方法 idea 定義為默認方法 ,  然后又在另一個接口 B 或者超類 C 中定義了同樣的方法 idea , 然后類 D 實現(xiàn)了這兩個接口 A 和 B(或超類 C) 。于是類 D 中就有了方法 idea 的兩個默認實現(xiàn) , 出現(xiàn)了沖突 , 為此 , Java 制定了一套規(guī)則來解決這個二義性問題:
1 ) 「超類優(yōu)先」 。如果超類提供了一個具體方法 , 接口中的同名且有相同參數(shù)類型的默認方法會被忽略 。
2 ) 「接口沖突」 。如果一個父類接口提供了一個默認方法 , 另一個父類接口也提供了一個同名而且參數(shù)類型相同的方法 , 子類必須覆蓋這個方法來解決沖突 。例如:
interface A { default void idea(){System.out.println("this is A"); }}interface B { default void idea(){System.out.println("this is B"); }}// 需要在 D 類中覆蓋 idea 方法class D implements A, B{public void getName(){System.out.println("this is D");}}現(xiàn)在假設(shè) B接口沒有為 idea 提供默認實現(xiàn):
interface B { void idea();}那么 D 類會直接從 A 接口繼承默認方法嗎?這好像挺有道理 ,  不過 , Java 設(shè)計者更強調(diào)一致性 。兩個接口如何沖突并不重要 , 「只要有一個接口提供了一個默認實現(xiàn) , 編譯器就會報告錯誤 ,  我們就必須解決這個二義性」 。
當(dāng)然 , 如果兩個接口都沒有為共享方法提供默認實現(xiàn) ,  那么就與 Java 8 之前的情況一樣 , 這里不存在沖突 。
5. 接口存在的意義在我自己早期學(xué)習(xí)編程的時候 , 對接口存在的意義實在困惑 , 我自己亂寫代碼的時候基本上不可能意識到需要去寫接口 , 不知道接口到底有什么用 , 為什么要定義接口 , 感覺定義接口只是提前做了個多余的工作 。
其實不是 , 定義接口并非多余 , 「接口是用來提供公用的方法 , 規(guī)定子類的行為的」 。舉個例子 , 讓大家直觀地感受下接口的作用:
比如有個網(wǎng)站 ,  需要保存不同客戶的信息 ,  有些客戶從 Web 網(wǎng)站來 ,  有些客戶從手機客戶端來 ,  有些客戶直接從后臺管理系統(tǒng)錄入 。假設(shè)不同來源的客戶有不同的處理業(yè)務(wù)流程 ,  這個時候我們定義接口來提供一個保存客戶信息的方法 , 然后不同的平臺實現(xiàn)我們這個保存客戶信息的接口 , 以后保存客戶信息的話 ,  我們只需要知道這個接口就可以了 , 具體調(diào)用的方法被封裝成了黑盒子 , 這也就是 Java 的多態(tài)的體現(xiàn) , 「接口幫助我們對這些有相同功能的方法做了統(tǒng)一管理」 。
一文讀懂java接口的特點 java接口的作用和意義例子

文章插圖
再比如說 , 我們要做一個畫板程序 , 其中里面有一個面板類 , 主要負責(zé)繪畫功能 , 然后你就定義了這個類 , 可是在不久的將來 , 你突然發(fā)現(xiàn)這個類滿足不了你了 , 然后你又要重新設(shè)計這個類 , 更糟糕是你可能要廢棄這個現(xiàn)有的類 , 那么其他引用這個類的地方也需要做出修改 , 顯然這樣非常麻煩 。
【一文讀懂java接口的特點 java接口的作用和意義例子】如果你一開始定義了一個接口 , 把繪畫功能放在這個接口里 , 然后定義類時實現(xiàn)這個接口 , 那么你只需要用這個接口去引用實現(xiàn)它的類就行了 , 以后要修改的話只不過是引用另一個類而已 。「接口的使用提高了代碼的可維護性和可擴展性」 。
另外 , 從這兩個例子我們也能看出 , 接口不僅「降低了代碼的耦合度」 , 而且僅僅描敘了程序?qū)ν獾姆?wù) , 不涉及任何具體的實現(xiàn)細節(jié) , 這樣也就比較「安全」一些 。

    推薦閱讀