Java接口的變更過程

Java 接口相信所有學過 Java 的人一定都知道,而且 99% 的人一定都背過這個面試題:Java 接口和抽象類的區別是什么?答案都是什么接口方法不能有實現,都是抽象的,接口的方法都默認為 public 修飾等等之類的,這些在 Java 8 之前是正確的,但是隨著 Java 的發展,它不再是正確的了。

一起來探索 Java 接口的進化之路。

出生:Java 1.0 引入接口

Java 1.0 ,作為 Java 語言的最初版本,于 1996 年發布。在這個版本中,Java 引入了接口(Interface)這一概念,標志著面向對象編程(OOP)在 Java 中的深入應用。

在 Java 1.0 中,接口被定義為完全抽象的,它具備如下特點:

  • 完全抽象:接口被定義為完全抽象,意味著它不能包含任何方法的具體實現。
  • 只能包含方法簽名和常量:接口中只能聲明方法簽名(沒有方法體)和公共靜態常量(public static final)。這意味著,在接口中定義的所有字段都會自動成為公共、靜態、最終的,而所有方法都被視為公共的和抽象的。
  • 沒有構造函數:接口不能被實例化,所以它們不能包含構造函數。
  • 多重實現:不同于類的繼承,Java 允許一個類實現多個接口。由于 Java 只允許單繼承,所以接口的出現,為 Java 的多重繼承提供了實現的可能。
  • 實現類必須實現所有方法:任何一個實現接口的類都必須實現接口中聲明的所有方法,除非該類被聲明為抽象類。

這個時候定義接口只能定義為如下形式:

public interface MyInterface {String SK_URL = "https://example.com/";String getSeriesUrl();
}

屬性 SK_URL 默認為 public static final

Java 1.1 引入內部類,內部類提供了一種強大的機制,它允許將一個類的定義放置在另一個類的定義內部,從而與外部類緊密地綁定在一起。內部類中的匿名內部類,可以用于實現接口,這對接口的使用有著特別的意義,它提高了代碼的封裝性和可維護性。

會爬了:Java 1.5 引入泛型

Java 5 于 2004 年發布,它引入了泛型,泛型的引入對接口的使用產生了深遠的影響。

在引入泛型之前,Java 接口通常處理的是 Object 類型的數據,這意味著任何類型的對象都可以傳遞給這些接口。在實現類中我們需要將 Object 類型的數據轉換為其它具體類型,這種轉換可能會導致 ClassCastException。

引入泛型后,接口可以在定義時就指定具體的類型參數,這使得接口在編譯時就能夠檢查和確認數據類型,從而大大增強了類型安全。同時,泛型允許接口定義通用的模板,例如List<E>Comparator<T>,這些接口可以被不同類型的數據重用,而不需要為每種數據類型創建新的接口。

下面舉一個簡單的例子來說明,引入 泛型對接口好處。

在 Java 5 引入泛型之前,集合類如 List 接口存儲的元素類型是不確定的,它們默認存儲 Object 類型的對象。這使得集合可以存儲任何類型的對象,但也帶來了類型安全問題。

List list = new ArrayList();
list.add("skjava.com");
list.add(1); // 這是合法的,因為集合可以存儲任何類型的對象// 獲取時需要進行類型轉換
String str = (String) list.get(0);
Integer num = (Integer) list.get(1);

list 可以同時存儲 String 和 Integer。但是,在獲取元素時,我們需要進行顯式的類型轉換。如果在運行時類型不匹配,會拋出 ClassCastException。

引入泛型后,可以在定義集合時指定存儲的元素類型。這提高了類型安全,并減少了運行時的錯誤。

List<String> list = new ArrayList<>();
list.add("skjava.com");
// list.add(1);       // 這行代碼會導致編譯錯誤,因為 list 只能存儲字符串// 獲取時不需要進行類型轉換
String str = list.get(0);

list 被定義為僅能存儲 String 類型的 List,當嘗試添加非 String 類型(如 Integer)到該 list 中會在編譯時報錯,而不是在運行時。同時,獲取元素時也不需要顯式的類型轉換,因為編譯器已經確保了所有元素都是 String 類型。

會走路了:Java 8 引入默認方法和靜態方法

Java 8 是一個重大的里程碑,因為它為Java接口引入了兩個重要的新特性:默認方法和靜態方法,這兩個特性讓 Java 接口可以走路了。

在 Java 8 之前,接口中申明的方法必須是抽象的,實現該接口就需要實現該接口的所有方法。我們知道接口的設計是一項巨大的工作,因為如果我們需要在接口中新增一個方法,需要對它的所有實現類都進行修改,如果它的實現類比較少還可以接受,如果實現類比較多則工作量就比較大了。而且有些實現類根本不需要實現該方法,也由于 Java 接口的限制導致它強迫實現該方法。

為了解決這個問題,Java 8 引入了默認方法,默認方法允許在接口中添加具有默認實現的方法,它使得接口可以包含方法的實現,而不僅僅是抽象方法的定義。這一特性可以在不破壞現有實現的前提下向接口添加新方法,使得接口具備了向后兼容的能力。

用法如下:

  • 使用default關鍵字標識方法,然后方法提供具體實現。
public interface MyInterface {default void print() {System.out.println("我是大明哥");}
}

實現接口的類可以直接使用這些默認方法,或者根據需要重寫它們:

public class MyInterfaceImpl implements MyInterface{@Overridepublic void print() {System.out.println("我是大明哥 2 號");}
}

Java 8 中還允許在接口中定義靜態方法。這些方法與類中的靜態方法一樣,是屬于接口的而不是接口的實例。靜態方法主要用于提供輔助方法,例如根據傳入參數構建接口的實現,或者提供通用的工具方法。

用法:

  • 靜態方法使用static關鍵字聲明,并且必須提供實現。
  • 是通過接口名直接調用靜態方法,不需要接口的實例。
public interface MyInterface {static int add(int a, int b) {return a + b;}
}

add() 是通過MyInterface.add(5, 3)直接調用,而不需要創建MyInterface的實例。

Java 引入默認方法和靜態方法大大增強了 Java 接口的能力,提高了 Java 接口的靈活性和功能性。

更多關于接口默認方法和靜態方法,閱讀:Java 8 新特性—接口默認方法和靜態方法

可以跑了:Java 9 引入私有方法

Java 8 為引入了默認方法和靜態方法,提高了 Java 接口的靈活性和功能性。但是這些依然是 public 的,這在某些情況下會導致了代碼重復和封裝性不足的問題。為了解決這個問題,Java 9 引入私有方法。

  • 私有方法只能在定義它們的接口內部被訪問。這就意味著接口可以有自己的內部邏輯,而不必將所有邏輯都暴露給實現該接口的類。這樣,接口的設計者可以更好地控制接口的行為,并防止實現類誤用接口內部的代碼,增強了接口的封裝性。
  • 由于私有方法只能在接口內部使用,無法在接口的實現類中被濫用,這有助于保持接口的一致性和約定。

在接口中使用私有方法有如下幾個限制:

  1. 私有方法不能是抽象的。
  2. 私有方法只能在接口內部使用,無法被接口的實現類或外部類訪問。
  3. 私有方法不會繼承給接口的子接口,每個接口都必須自己定義自己的私有方法。
  4. 私有靜態方法可以在其他靜態和非靜態接口方法中使用。
  5. 私有非靜態方法不能在私有靜態方法內部使用。

下面是私有方法的簡單使用:

public interface MyInterface {private void print() {System.out.println("我是大明哥");}
}

總示例

下面用一個例子來演示上面所有功能。

public interface MyInterface {String NAME = "MyInterface";/*** 抽象方法,所有實現類都要實現* @return*/void abstractMethod();/*** 默認方法*/default void defaultMethod() {//默認方法里可以調用私有方法privateMethod();// 默認方法可以調用靜態私有方法staticPrivateMethod();System.out.println("默認方法-MyInterface-defaultMethod");}/*** 靜態方法* @return*/static void staticMethod() {// 靜態方法只能調用靜態私有方法,不能調用私有方法System.out.println("靜態方法-MyInterface-staticMethod");}/*** 私有方法*/private void privateMethod() {System.out.println("私有方法-MyInterface-privateMethod");}/*** 靜態私有方法*/private static void staticPrivateMethod() {System.out.println("靜態私有方法-MyInterface-staticPrivateMethod");}
}

接口 MyInterface 里面定義了抽象方法,默認方法,靜態方法,私有方法。這里要注意一下幾點:

  1. 私有方法為接口所有,只能在接口的默認方法中調用。
  2. 靜態私有方法既可以在靜態方法中調用,也可以在默認方法中調用。
  3. 默認方法也可以調用靜態方法,但是靜態方法不能調用默認方法。
  • 兩個實現類
public class MyImplements1 implements MyInterface{@Overridepublic void abstractMethod() {// 調用接口的靜態方法MyInterface.staticMethod();System.out.println("抽象方法-MyImplements1-getName");}/*** 重寫默認方法*/@Overridepublic void defaultMethod() {System.out.println("重寫默認方法-MyImplements1-defaultMethod");}
}public class MyImplements2 implements MyInterface{@Overridepublic void abstractMethod() {// 調用接口的靜態方法MyInterface.staticMethod();System.out.println("抽象方法-MyImplements1-getName");}
}

MyImplements1 重寫了默認方法。所以當我們調用 MyImplements1 示例對象的 defaultMethod() 時,會調用到重寫的這個方法。

  • 測試
public class InterfaceTest {public static void main(String[] args) {MyInterface implements1 = new MyImplements1();MyInterface implements2 = new MyImplements2();implements1.abstractMethod();implements1.defaultMethod();System.out.println("===========================");implements2.abstractMethod();implements2.defaultMethod();}
}
  • 運行結果
靜態方法-MyInterface-staticMethod
抽象方法-MyImplements1-getName
重寫默認方法-MyImplements1-defaultMethod
===========================
靜態方法-MyInterface-staticMethod
抽象方法-MyImplements1-getName
私有方法-MyInterface-privateMethod
靜態私有方法-MyInterface-staticPrivateMethod
靜態方法-MyInterface-staticMethod
默認方法-MyInterface-defaultMethod

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

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

相關文章

推箱子小游戲C++

推箱子是一款經典的益智游戲&#xff0c;玩家需要通過推動箱子來達到特定的目標。在C中實現這樣的小游戲需要考慮游戲邏輯、用戶輸入、圖形界面&#xff08;如果需要的話&#xff09;以及可能的關卡設計。 下面是一個簡單的推箱子游戲的實現框架&#xff1a; 定義游戲環境 創建…

DSP問題:CCS更改工程名導入報錯

1、問題現象 復制一個工程出來后&#xff0c;修改版本號&#xff0c;重新導入工程后報錯。 顯示項目描述無效。 2、問題原因 由于CCS無法通過工程描述中找到指定名字文件夾。使用記事本打開.project文件&#xff0c;里面的描述還是以前的文件夾名&#xff0c;所以導入時報…

Spring Boot 開發 -- 靜態資源配置詳解

一、引言 在開發Web應用程序時&#xff0c;靜態資源的管理和配置是一個重要的環節。Spring Boot框架為開發者提供了便捷的靜態資源配置方式&#xff0c;使得我們可以輕松地管理如HTML、CSS、JavaScript、圖片等靜態資源。本文將詳細介紹如何在Spring Boot項目中配置和管理靜態…

Innodb Buffer Pool緩存機制(三)Innodb Buffer Pool內部組成

一、控制塊緩存頁 Buffer Pool中默認的緩存頁大小和在磁盤上默認的頁大小是一樣的&#xff0c;都是16KB。為了更好的管理這些在Buffer Pool中的緩存頁&#xff0c;InnoDB為每一個緩存頁都創建了一些所謂的控制信息&#xff0c;這些控制信息包括該頁所屬的表空間編號、頁號、緩存…

Android基礎-AndroidManifest.xml詳解

在Android開發中&#xff0c;AndroidManifest.xml 文件是一個至關重要的組成部分&#xff0c;它位于應用的根目錄的 app/src/main/ 文件夾下。這個文件提供了Android系統和其他應用所需的所有關于應用的元數據信息。以下是對 AndroidManifest.xml 文件的詳細解析。 1. 文件結構…

[Vulfocus解題系列]spring 命令執行(CVE-2022-22947)

環境部署 使用docker部署環境 漏洞等級&#xff1a;高危 3 月 1 日&#xff0c;VMware 官方發布安全公告&#xff0c;聲明對 Spring Cloud Gateway 中的一處命令注入漏洞進行了修復&#xff0c;漏洞編號為CVE-2022-22947 Spring官方發布 漏洞描述 使用 Spring Cloud Gate…

javaweb—Vue

重點為&#xff1a;雙向數據綁定。 框架&#xff1a;是一個半成品軟件&#xff0c;是一套可重用的、通用的、軟件基礎代碼模型&#xff0c;基于框架進行開發&#xff0c;更加快捷&#xff0c;更加高效。 Vue快速入門 基礎框架&#xff1a; <!DOCTYPE html> <html lan…

【Python Cookbook】S01E20 fnmatch 模塊做字符串匹配

目錄 問題解決方案討論 問題 在不同的操作系統下&#xff0c;怎樣做字符串匹配&#xff1f; 解決方案 fnmatch() 模塊提供兩個函數&#xff0c;fnmatch() 以及 fnmatchcase() 可以用來執行做這樣的匹配。 from fnmatch import fnmatch, fnmatchcasematch_res fnmatch(foo.…

vue路由緩存

vue路由緩存 在業務場景中有時候需要頁面緩存不清空&#xff0c;那么就需要保留緩存(include為需要緩存&#xff0c;而exclude為不緩存&#xff0c;且優先級大于include) <KeepAlive> 是一個內置組件&#xff0c;它的功能是在多個組件間動態切換時緩存被移除的組件實例…

【java 為什么說 Synchronized 是非公平鎖?】

文章目錄 概要1. 非公平鎖的定義2. synchronized 作為非公平鎖的原因3. 非公平鎖的特點4. 如何實現公平鎖總結 概要 在Java中&#xff0c;synchronized 關鍵字用于實現同步&#xff0c;以確保在多線程環境下對共享資源的訪問是線程安全的。然而&#xff0c;synchronized 實現的…

03-3.1.2 棧的順序存儲的實現

&#x1f44b; Hi, I’m Beast Cheng&#x1f440; I’m interested in photography, hiking, landscape…&#x1f331; I’m currently learning python, javascript, kotlin…&#x1f4eb; How to reach me --> 458290771qq.com 喜歡《數據結構》部分筆記的小伙伴可以訂…

郵件地址搜索軟件

易郵件地址搜索大師  一、易郵件地址搜索大師特色 — 易郵件地址搜索大師是一款搜索郵件地址和手機號碼的軟件&#xff0c;可以按整站搜索&#xff0c;也可以按關鍵詞搜索。使用方法非常簡單和方便。 — “整站搜索”可以搜索有很多郵件地址的單一網站&#xff0c;主要用于…

Technart電動螺絲刀TN101控制器維修

Technart電動螺絲刀以其高效、穩定和精確的扭矩控制而聞名。然而&#xff0c;即使優質的產品&#xff0c;在長時間的使用下&#xff0c;也可能會出現TECHNART電動螺母扳手控制器故障。 常見故障及維修方法 1. 控制器不工作 癥狀&#xff1a;電動螺絲刀無法啟動&#xff0c;或啟…

Python怎么染色:深入探索Python中的文本和圖形著色技巧

Python怎么染色&#xff1a;深入探索Python中的文本和圖形著色技巧 在Python編程中&#xff0c;染色或著色不僅限于文本輸出&#xff0c;還涉及圖形、圖像甚至數據可視化的多個層面。本文將帶你走進Python的染色世界&#xff0c;從四個方面、五個方面、六個方面和七個方面詳細…

【WEEK15】 【DAY2】【DAY3】Email Tasks【English Version】

Continuation from【WEEK15】 【DAY1】Asynchronous Tasks【English Version】 Contents 17. Asynchronous, Timed, and Email Tasks17.2. Email Tasks17.2.1. Email sending is also very common in our daily development, and Springboot provides support for this as well…

用戶的權限

一&#xff0c;用戶權限基礎知識 1&#xff0c;用戶的權限有&#xff1a; r&#xff1a;讀 w&#xff1a;寫 x&#xff1a;執行 2&#xff0c;文件的權限&#xff1a; r&#xff1a;可以執行cat、head、tail等命令讀取文件中的內容 w&#xff1a;可以用vi/vim或者重定向等…

JeecgBoot/SpringBoot升級Nacos(2.0.4到2.2.3)啟動報錯

錯誤如下&#xff1a; 報這種錯誤基本就很頭大了&#xff0c;是框架不兼容的問題&#xff0c;自己找很難找到解決方法。 解決方案是把SpringBoot框架版本調高。 修改前&#xff1a; <parent><groupId>org.springframework.boot</groupId><artifactId&g…

Dell戴爾XPS 16 9640 Intel酷睿Ultra9處理器筆記本電腦原裝出廠Windows11系統包,恢復原廠開箱狀態oem預裝系統

下載鏈接&#xff1a;https://pan.baidu.com/s/1j_sc8FW5x-ZreNrqvRhjmg?pwd5gk6 提取碼&#xff1a;5gk6 戴爾原裝系統自帶網卡、顯卡、聲卡、藍牙等所有硬件驅動、出廠主題壁紙、系統屬性專屬聯機支持標志、系統屬性專屬LOGO標志、Office辦公軟件、MyDell、邁克菲等預裝軟…

Linux基礎 (十四):socket網絡編程

我們用戶是處在應用層的&#xff0c;根據不同的場景和業務需求&#xff0c;傳輸層就要為我們應用層提供不同的傳輸協議&#xff0c;常見的就是TCP協議和UDP協議&#xff0c;二者各自有不同的特點&#xff0c;網絡中的數據的傳輸其實就是兩個進程間的通信&#xff0c;兩個進程在…

32C3-2模組與樂鑫ESP32--C3--WROOM--02模組原理圖、升級口說明

模組原理圖&#xff1a; 底板原理圖&#xff1a; u1 是AT通信口&#xff0c;wiif-tx wifi-rx 是升級口&#xff0c;chip-pu是reset復位口&#xff0c;GPIO9拉低復位進入下載模式 ESP32-WROOM-32 系列硬件連接管腳分配? 功能 ESP32 開發板/模組管腳 其它設備管腳 下載固件…