java 空接口_學Java,java接口搞明白了嗎?大牛讓你一文搞清楚

76366827120ed40fa574476ff9ff6c5e.png

前言

對于面向對象編程來說,抽象是一個極具魅力的特征。如果一個程序員的抽象思維很差,那他在編程中就會遇到很多困難,無法把業務變成具體的代碼。在 Java 中,可以通過兩種形式來達到抽象的目的,一種是抽象類,另外一種就是接口。

如果你現在就想知道抽象類與接口之間的區別,我可以提前給你說一個:

  • 一個類只能繼承一個抽象類,但卻可以實現多個接口。

當然了,在沒有搞清楚接口到底是什么,它可以做什么之前,這個區別理解起來會有點難度。

01、接口是什么

接口是通過 interface 關鍵字定義的,它可以包含一些常量和方法,來看下面這個示例。

public?interface?Electronic?{????//?常量????String?LED?=?"LED";????//?抽象方法????int?getElectricityUse();????//?靜態方法????static?boolean?isEnergyEfficient(String?electtronicType)?{????????return?electtronicType.equals(LED);????}????//?默認方法????default?void?printDescription()?{????????System.out.println("電子");????}}

1)接口中定義的變量會在編譯的時候自動加上 public static final 修飾符,也就是說 LED 變量其實是一個常量。

Java 官方文檔上有這樣的聲明:

Every field declaration in the body of an interface is implicitly public, static, and final.

換句話說,接口可以用來作為常量類使用,還能省略掉 public static final,看似不錯的一種選擇,對吧?

不過,這種選擇并不可取。因為接口的本意是對方法進行抽象,而常量接口會對子類中的變量造成命名空間上的“污染”。

2)沒有使用 private、default 或者 static 關鍵字修飾的方法是隱式抽象的,在編譯的時候會自動加上 public abstract 修飾符。也就是說 getElectricityUse() 其實是一個抽象方法,沒有方法體——這是定義接口的本意。

3)從 Java 8 開始,接口中允許有靜態方法,比如說 isEnergyEfficient() 方法。

靜態方法無法由(實現了該接口的)類的對象調用,它只能通過接口的名字來調用,比如說 Electronic.isEnergyEfficient("LED")。

接口中定義靜態方法的目的是為了提供一種簡單的機制,使我們不必創建對象就能調用方法,從而提高接口的競爭力。

4)接口中允許定義 default 方法也是從 Java 8 開始的,比如說 printDescription(),它始終由一個代碼塊組成,為實現該接口而不覆蓋該方法的類提供默認實現,也就是說,無法直接使用一個“;”號來結束默認方法——編譯器會報錯的。

d6d0cb2cc870d9e4ae4805f3c128cee9.png

允許在接口中定義默認方法的理由是很充分的,因為一個接口可能有多個實現類,這些類就必須實現接口中定義的抽象類,否則編譯器就會報錯。假如我們需要在所有的實現類中追加某個具體的方法,在沒有 default 方法的幫助下,我們就必須挨個對實現類進行修改。

來看一下 Electronic 接口反編譯后的字節碼吧,你會發現,接口中定義的所有變量或者方法,都會自動添加上 public 關鍵字——假如你想知道編譯器在背后都默默做了哪些輔助,記住反編譯字節碼就對了。

public?interface?Electronic{????public?abstract?int?getElectricityUse();????public?static?boolean?isEnergyEfficient(String?electtronicType)????{????????return?electtronicType.equals("LED");????}????public?void?printDescription()????{????????System.out.println("電子");????}????public?static?final?String?LED?=?"LED";}

02、定義接口的注意事項

由之前的例子我們就可以得出下面這些結論:

  • 接口中允許定義變量
  • 接口中允許定義抽象方法
  • 接口中允許定義靜態方法(Java 8 之后)
  • 接口中允許定義默認方法(Java 8 之后)

除此之外,我們還應該知道:

1)接口不允許直接實例化。

1588cf5d53229362f67d91c2794289a1.png

需要定義一個類去實現接口,然后再實例化。

public?class?Computer?implements?Electronic?{????public?static?void?main(String[]?args)?{????????new?Computer();????}????@Override????public?int?getElectricityUse()?{????????return?0;????}}

2)接口可以是空的,既不定義變量,也不定義方法。

public?interface?Serializable?{}

Serializable 是最典型的一個空的接口,相關Serializable 的知識點之后我會繼續分享!

3)不要在定義接口的時候使用 final 關鍵字,否則會報編譯錯誤,因為接口就是為了讓子類實現的,而 final 阻止了這種行為。

afdcae40c01706e3c86c39692f70bd5a.png

4)接口的抽象方法不能是 private、protected 或者 final。

f95e92be1a81ee1bd515b4dd452bdc0f.png
2e23664216c5d3e55b7bd11ace094423.png
f8c1ac71bb3160684c07b8bf175218d7.png

5)接口的變量是隱式 public static final,所以其值無法改變。

03、接口可以做什么

1)使某些實現類具有我們想要的功能,比如說,實現了 Cloneable 接口的類具有拷貝的功能,實現了 Comparable 或者 Comparator 的類具有比較功能。

Cloneable 和 Serializable 一樣,都屬于標記型接口,它們內部都是空的。實現了 Cloneable 接口的類可以使用 Object.clone() 方法,否則會拋出 CloneNotSupportedException。

public?class?CloneableTest?implements?Cloneable?{????@Override????protected?Object?clone()?throws?CloneNotSupportedException?{????????return?super.clone();????}????public?static?void?main(String[]?args)?throws?CloneNotSupportedException?{????????CloneableTest?c1?=?new?CloneableTest();????????CloneableTest?c2?=?(CloneableTest)?c1.clone();????}}

運行后沒有報錯。現在把 implements Cloneable 去掉。

public?class?CloneableTest?{????@Override????protected?Object?clone()?throws?CloneNotSupportedException?{????????return?super.clone();????}????public?static?void?main(String[]?args)?throws?CloneNotSupportedException?{????????CloneableTest?c1?=?new?CloneableTest();????????CloneableTest?c2?=?(CloneableTest)?c1.clone();????}}

運行后拋出 CloneNotSupportedException:

Exception?in?thread?"main"?java.lang.CloneNotSupportedException:?com.cmower.baeldung.interface1.CloneableTest????at?java.base/java.lang.Object.clone(Native?Method)????at?com.cmower.baeldung.interface1.CloneableTest.clone(CloneableTest.java:6)????at?com.cmower.baeldung.interface1.CloneableTest.main(CloneableTest.java:11)

2)Java 原則上只支持單一繼承,但通過接口可以實現多重繼承的目的。

為什么 Java 只支持單一繼承?”簡單來解釋一下。

如果有兩個類共同繼承(extends)一個有特定方法的父類,那么該方法會被兩個子類重寫。然后,如果你決定同時繼承這兩個子類,那么在你調用該重寫方法時,編譯器不能識別你要調用哪個子類的方法。這也正是著名的菱形問題,見下圖。

a8184b20b9f90c84ceab50f7622cda51.png

ClassC 同時繼承了 ClassA 和 ClassB,ClassC 的對象在調用 ClassA 和 ClassB 中重載的方法時,就不知道該調用 ClassA 的方法,還是 ClassB 的方法。

接口沒有這方面的困擾。來定義兩個接口,Fly 會飛,Run 會跑。

public?interface?Fly?{????void?fly();}public?interface?Run?{????void?run();}

然后讓一個類同時實現這兩個接口。

public?class?Pig?implements?Fly,Run{????@Override????public?void?fly()?{????????System.out.println("會飛的豬");????}????@Override????public?void?run()?{????????System.out.println("會跑的豬");????}}

這就在某種形式上達到了多重繼承的目的:現實世界里,豬的確只會跑,但在雷軍的眼里,站在風口的豬就會飛,這就需要賦予這只豬更多的能力,通過抽象類是無法實現的,只能通過接口。

3)實現多態。

什么是多態呢?通俗的理解,就是同一個事件發生在不同的對象上會產生不同的結果,鼠標左鍵點擊窗口上的 X 號可以關閉窗口,點擊超鏈接卻可以打開新的網頁。

多態可以通過繼承(extends)的關系實現,也可以通過接口的形式實現。來看這樣一個例子。

Shape 是表示一個形狀。

public?interface?Shape?{????String?name();}

圓是一個形狀。

public?class?Circle?implements?Shape?{????@Override????public?String?name()?{????????return?"圓";????}}

正方形也是一個形狀。

public?class?Square?implements?Shape?{????@Override????public?String?name()?{????????return?"正方形";????}}

然后來看測試類。

List?shapes?=?new?ArrayList<>();Shape?circleShape?=?new?Circle();Shape?squareShape?=?new?Square();shapes.add(circleShape);shapes.add(squareShape);for?(Shape?shape?:?shapes)?{????System.out.println(shape.name());}

多態的存在 3 個前提:

1、要有繼承關系,Circle 和 Square 都實現了 Shape 接口2、子類要重寫父類的方法,Circle 和 Square 都重寫了 name() 方法3、父類引用指向子類對象,circleShape 和 squareShape 的類型都為 Shape,但前者指向的是 Circle 對象,后者指向的是 Square 對象。

然后,我們來看一下測試結果:

圓正方形

也就意味著,盡管在 for 循環中,shape 的類型都為 Shape,但在調用 name() 方法的時候,它知道 Circle 對象應該調用 Circle 類的 name() 方法,Square 對象應該調用 Square 類的 name() 方法。

04、接口與抽象類的區別

1)語法層面上

  • 接口中不能有 public 和 protected 修飾的方法,抽象類中可以有。
  • 接口中的變量只能是隱式的常量,抽象類中可以有任意類型的變量。
  • 一個類只能繼承一個抽象類,但卻可以實現多個接口。

2)設計層面上

抽象類是對類的一種抽象,繼承抽象類的類和抽象類本身是一種 is-a 的關系。

接口是對類的某種行為的一種抽象,接口和類之間并沒有很強的關聯關系,所有的類都可以實現 Serializable 接口,從而具有序列化的功能。

就這么多吧,能說道這份上,我相信面試官就不會為難你了。

大家記得關注奧,我會繼續和大家分享,感謝你們的閱讀和陪伴!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455523.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455523.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455523.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Check Point CEO:“我們正在積極尋找收購目標”

Check Point Sofrware Technologies很可能成為下一個會產生收購案的主流安全廠商&#xff0c;首席執行官Gil Shwed在該公司第二季度財報電話會議上這樣表示。 “我們正在積極地尋求收購目標&#xff0c;期待無論是大規模的還是小規模的擴張&#xff0c;”Shwed表示。“我們在并…

Spark SQL 編程API入門系列之SparkSQL數據源

不多說&#xff0c;直接上干貨&#xff01; SparkSQL數據源&#xff1a;從各種數據源創建DataFrame 因為 spark sql&#xff0c;dataframe&#xff0c;datasets 都是共用 spark sql 這個庫的&#xff0c;三者共享同樣的代碼優化&#xff0c;生成以及執行流程&#xff0c;所以 s…

H.264中的一些易混淆概念

Q:PSNR 峰值信噪比 Q:是根據它來取qp是不是&#xff1f; A:不是, 和QP沒有直接關系, 但是QP的選擇會影響到PSNR Q: 如果不用率失真最優化&#xff0c; 為什么選擇SATD&#xff0b;deltar&#xff08;mv&#xff0c;mode&#xff09;作為模式選擇的依據&#xff1f;為什么運…

Java中final關鍵字的幾種用法

在java的關鍵字中&#xff0c;static和final是兩個我們必須掌握的關鍵字。不同于其他關鍵字&#xff0c;他們都有多種用法&#xff0c;而且在一定環境下使用&#xff0c;可以提高程序的運行性能&#xff0c;優化程序的結構。下面我們來了解一下final關鍵字及其用法。 final關鍵…

python pyqt5安裝_Python3 安裝PyQt5及exe打包圖文教程

環境: Python 3.6.4 Pycharm Professional 2017.3.3 PyQt5 PyQt5-tools① Python 3 安裝Python 3.x 安裝時&#xff0c;默認勾選ADD Python 3.6 to PATH和ADD Python to environment variables的情況下&#xff0c;系統會向path中增加以下兩個環境變量。D:\Program Files\Py…

《企業軟件交付:敏捷與高效管理精要》——3.4 企業軟件交付的軟件工廠方法...

3.4 企業軟件交付的軟件工廠方法 正如我們前面討論的&#xff0c;今天的機構面對的商業環境正以前所未有的速度發生變化。與此同時&#xff0c;這些機構還要管理和降低整個機構的運營成本。這就直接意味著&#xff0c;他們不僅要最大限度地減少浪費和低效率&#xff0c;還要提…

201706問題記錄

1.四周陰影 box-shadow:0px 0px 10px #f5f5f5; 2. 原生setattribute()方法 jquery的attr()$(.fd-sq-zk).attr("title","收起"); 3.在iframe中獲取外層容器的元素 屬性等 $(parent.document).find("html")..... 4.監聽頁面變大變小事件 /…

一致性hash算法_(圖文案例)一致性哈希算法詳解 一點課堂(多岸教育)

一致性Hash算法關于一致性Hash算法&#xff0c;在我之前的博文中已經有多次提到了&#xff0c;MemCache超詳細解讀一文中”一致性Hash算法”部分&#xff0c;對于為什么要使用一致性Hash算法、一致性Hash算法的算法原理做了詳細的解讀。算法的具體原理這里再次貼上&#xff1a;…

《HTML5 Canvas游戲開發實戰》——2.1 繪制基本圖形

本節書摘來自華章計算機《HTML5 Canvas游戲開發實戰》一書中的第2章&#xff0c;第2.1節,作者&#xff1a;張路斌著&#xff0c; 更多章節內容可以訪問云棲社區“華章計算機”公眾號查看。 2.1 繪制基本圖形 所謂基本圖形&#xff0c;就是指線、矩形、圓等最簡單的圖形&#x…

如何查看Ubuntu版本

有時候需要查看一下系統安裝的Ubuntu的版本&#xff0c;最簡單的方式是輸入lsb_release -a。whatis lsb_release輸出&#xff1a;print distribution-specific information。所以lsb_release這個命令就是用來輸出發行版的信息的。 Open the Terminal enter:lsb_release -a It w…

linux下.a/.so/.la目標庫區別

在linux平臺上編譯時&#xff0c;常會遇到目標庫的疑問&#xff0c;有靜態庫也有動態庫&#xff0c;單個理解都不太難&#xff0c;但是對復雜的工程而言&#xff0c;一旦混合到一起去&#xff0c;對整個工程的理解和調用&#xff0c;將會造成很大困擾&#xff0c;本文就匯總這幾…

python 二元函數繪制_Python繪制二元函數曲面

微實踐&#xff1a;繪制二元函數曲面我們將演示如何借助于ufunc的廣播運算計算下述二元函數的在一個xy平面上的值并將其繪制成3D曲面。其中&#xff0c;x和y的取值范圍均為[-2,2]。為了達到目的&#xff0c;我們需要一個二維的結果數組z&#xff0c;其元素的下標對應參數x,y的取…

Npgsql使用入門(三)【批量導入數據】

Program.cs代碼: class Program{static void Main(string[] args){var test new PgBulkCopyHelper<SingleBuilding>("bld_amap_gzmain");foreach (string pName in test.PropNames){Console.WriteLine("name: {0},\t\ttype: {1}", pName, test.Prop…

遠程網絡視頻監視技術

目前要實現廣域網視頻監視&#xff0c;主要通過三種方式實現&#xff1a;1.硬盤錄像機&#xff1b;2.網絡視頻服務器&#xff1b;3.網絡攝像機。 硬盤錄像機是一個以錄像為主的設備&#xff0c;有的可以支持IE瀏覽。網絡視頻服務器一般前端不錄像&#xff0c;直接將影像傳輸到…

Deepin下java開發環境部署

簡介 本經驗由深度論壇用戶(zhang12345shun)分享&#xff0c;原文地址 正文 SUN JDK&#xff08;現已改名Oracle JDK&#xff09; 1.下載Sun版JDK壓縮包&#xff08;.tar.gz&#xff09;&#xff0c;選擇其中的32/64位Linux版本。 2.將其解壓縮&#xff1a; sudo tar -zx…

判斷ic卡類型

傳15讀卡片數據 判斷data8的status是否為0&#xff0c;是則是ic 否則就是磁條卡 根據二磁道數據識別是IC卡還是磁條卡 根據二磁道符號后面第一位識別。規則是 該數字 6 或者 2 則該卡是IC卡&#xff0c;否則是普通磁條卡 轉載于:https://www.cnblogs.com/wubenhui/p/6956256.h…

python常用代碼_Python常用算法學習(3)(原理+代碼)——最全總結

1&#xff0c;什么是算法的時間和空間復雜度算法(Algorithm)是指用來操作數據&#xff0c;解決程序問題的一組方法&#xff0c;對于同一個問題&#xff0c;使用不同的算法&#xff0c;也許最終得到的結果是一樣的&#xff0c;但是在過程中消耗的資源和時間卻會有很大的區別。那…

數據監測驅動下的信息流廣告優化

信息流廣告是什么 “今日頭條和百度必有一戰”&#xff0c;相信不少的互聯網人在過去幾個月都聽到過類似的斷言。定位于信息分發平臺的今日頭條和主營搜索業務的百度會產生如此大的利益沖突&#xff0c;最核心的點其實就是信息流廣告。 信息流廣告指的是在用戶使用互聯網產品或…

在idea中使用git管理你的項目

起步 idea是十分智能的Java集成開發環境 而我們在用idea寫項目的時候經常遇到版本控制的問題,而git工具如果你只會在終端中的git命令來進行控制,可能會使得效率低下 今天小編就教大家在idea中使用git來管理你的項目 首先創建一個項目 點擊create new projects 這里選擇默認…

react-native熱更新插件react-native-code-push

使用react-native-code-push插件來實現熱更新的時候&#xff0c;會遇到一些問題。下面這個問題就讓我差點崩潰了。 在測試 Production 和 Staging 是否會去檢查各自環境下的bundle文件&#xff0c;我就遇到了混亂的問題。 有時候用 Release 打包出來的app會去檢查 Staging 下的…