天天看點

「接口」Java 接口是什麼以及如何使用

接口簡概

接口概念:在 Java 程式設計語言中, 接口不是類,而是對類的一組需求描述,這些類要遵從接口描 述的統一格式進行定義 。

接口中的所有方法自動地屬于 public 。 是以,在接口中聲明方法時,不必提供關鍵字 public。

在接口中可以定義常量。然而,更為重要的是要知道接口不能提供哪些功能。接口絕不能含有執行個體域 。

在JavaSE 8時,可以在接口中提供簡單方法了。當然, 這些方法不能引用執行個體域——接口沒有執行個體。

提供執行個體域和方法實作的任務應該由實作接口的那個類來完成。是以,可以将接口看成是沒有執行個體域的抽象類,但是這兩個概念還是有一定差別的。

要将類聲明為實作某個接口, 需要使用關鍵字 implements。 為了讓類實作一個接口, 通常需要下面兩個步驟: 1 ) 将類聲明為實作給定的接口。 2 ) 對接口中的所有方法進行定義。

在接口聲明中,不需要将方法聲明為 public , 這是因為在接口中的所有方法都自動地是 public 。不過,在實作接口時, 必須把方法聲明為 public。

接口的特性

接口不是類,尤其不能使用 new運算符執行個體化一個接口。

盡管不能構造接口的對象,卻能聲明接口的變量。

Comparable x ; // OK

接口變量必須引用實作了接口的類對象 。

x = new Employee (. . .); // OK

如同使用 instanceof檢查一個對象是否屬于某個特定類一樣, 也可以使用 instanceof 檢查一個對象是否實作了某個特定的接口。

if (anObject instanceof Comparable) { . . . }

與可以建立類的繼承關系一樣,接口也可以被擴充,使用關鍵字 extends。這裡允許存在多條從具有較高通用性的接口到較高專用性的接口的鍊。

接口中的方法都自動地被設定為 public —樣,接口中的域将被自動設為 public static final。

可以将接口方法标記為 public, 将域标記為 public static final。有些程式員出于習慣或提高清晰度的考慮,願意這樣做。但 Java 語言規範卻建議不要書寫這些多餘的關鍵字。

每個類隻能夠擁有一個超類, 但卻可以實作多個接口。這為定義類的行為提供了極大的靈活性。

靜态方法

在 Java SE 8 中,允許在接口中增加靜态方法。理論上講,沒有任何理由認為這是不合法的。隻是這有違于将接口作為抽象規範的初衷。

目前為止, 通常的做法都是将靜态方法放在伴随類中。在标準庫中, 你會看到成對出現的接口和實用工具類, 如 Collection/Collections 或 Path/Paths 。

在Java SE 8 中, 可以為 Path 接口增加靜态方法,這樣一來, Paths 類就不再是必要的了。 不過整個 Java 庫都以這種方式重構也是不太可能的, 但是實作你自己的接口時,不再需要為實用工具方法另外提供一個伴随類。

預設方法

在 Java SE 8 中,可以為接口方法提供一個預設實作。 必須用 default 修飾符标記這樣一個方法。

有些情況下, 預設方法可能很有用。例如,隻對接口中的某幾個方法感興趣,而不是全部。

預設方法可以調用任何其他方法。

在 JavaAPI 中,你會看到很多接口都有相應的伴随類,這個伴随類中實作了相應接口 的部分或所有方法,如 Collection/AbstractCollection 或 MouseListener/MouseAdapter。在 JavaSE 8 中, 這個技術已經過時。現在可以直接在接口中實作方法。

預設方法的一個重要作用是“‘ 接口演化” (interface evolution)。 對于一些老版本的接口,如果要在上面增添新功能時,預設方法就不失為一個好的選擇,因為預設方法不會對以前的接口實作産生影響。為接口增加一個非預設方法不能保證“源代碼相容”(source compatible)。

解決預設方法沖突

如果先在一個接口中将一個方法定義為預設方法, 然後又在超類或另一個接口中定義了 同樣的方法, 會發生什麼情況? Java 的規則要簡單得多。

  1. 超類優先。如果超類提供了一個具體方法,同名而且有相同參數類型的預設方法會被忽略。“ 類優先” 規則可以確定與 Java SE 7 的相容性。如果為一個接口增加預設方法,這對于 有這個預設方法之前能正常工作的代碼不會有任何影響。
  2. 接口沖突。 如果一個超接口提供了一個預設方法,另一個接口提供了一個同名而且參數類型(不論是否是預設參數)相同的方法, 必須覆寫這個方法來解決沖突。
    • 當一個類要實作的接口中有多個相同的預設方法時,并不是從中選擇一個,Java 編譯器會報告一個錯誤,讓程式員來解決這個二義性。
    • 當一個類要實作的接口中有多個相同的方法時,如果至少有一個接口提供了一個實作,編譯器就會報告錯誤, 而程式員就必須解決這個二義性。Java 設計者更強調一緻性。兩個接口如何沖突并不重要。
    • 如果兩個接口都沒有為共享方法提供預設實作, 那麼就與 Java SE 8之前的 情況一樣,這裡不存在沖突。 實作類可以有兩個選擇:實作這個方法,或者幹脆不實作。 如果是後一種情況,這個類本身就是抽象的。

千萬不要讓一個預設方法重新定義 Object 類中的某個方法。例如,不能為 toString 或 equals 定義預設方法, 盡管對于 List 之類的接口這可能很有吸引力, 由于“ 類優先” 規則, 這樣的方法絕對無法超越 Object.toString 或 Objects.equals。

繼續閱讀