1、interface不僅僅只是一個極度抽象的類,因為它允許人們通過建立一個能夠被向上轉型為多種基底類型的類,來實現某種類似C++多重繼承變種的特性。
2、像類一樣,可以在interface關鍵字前面添加public關鍵字(但僅限於該介面在與其同名的檔案中被定義),或者不添加它而使其只是具有包存取權限,這樣它就只能在同一個包內可用。
3、可以選擇在介面中顯示地將方法聲明為public的,但即使你不這麼做,它們也是public的。因此當實現一個介面時,在介面中被定義的方法必須被定義為public。
4、Java中,在方法的繼承過程中,其可存取權限不能被降低。
5、介面也可以包含欄位,但是它們隱式為static和final的。
6、因為介面是根本沒有任何具體實現的——也就是說,沒有任何與介面相關的儲存;因此,也就無法阻止多個介面的組合,也就是“多重繼承”。如下例子:
interface CanFight{ void fight();}interface CanSwim{ void swim();}interface CanFly{ void fly();}class ActionCharacter{ public void fight(){ System.out.println("ActionCharacter.fight()"); }}class Hero extends ActionCharacter implements CanFight, CanSwim, CanFly{ public void swim(){ System.out.println("Hero.swim()"); } public void fly(){ System.out.println("Hero.fly()"); } /**1.注意CanFight中的fight()方法並沒在這裡定義 * 2.這是因為CanFight介面與ActionCharacter類中的fight()方法的特徵簽名是一樣的。 * 3.所以即使Hero沒有顯式地提供fight()的定義,其定義也因ActionCharacter而隨之而來。 * 4.若把ActionCharacter的fight()改為private,就會出現提示說 * “類型 Hero必須實現繼承的抽象方法 CanFight.fight()”的錯誤。 * 5.若把ActionCharacter的fight()改為private,就會出現提示說 * “繼承的方法 ActionCharacter.fight()不能隱藏 CanFight中的公用抽象方法”的錯誤。 */ }public class Adventure{ public static void t(CanFight x){x.fight();} public static void u(CanSwim x){x.swim();} public static void v(CanFly x){x.fly();} public static void w(ActionCharacter x){x.fight();} public static void main(String[] args){ Hero h = new Hero(); t(h); u(h); v(h); w(h); }}
運行結果:
1).注意CanFight中的fight()方法並沒有在Hero定義
2).這是因為CanFight介面與ActionCharacter類中的fight()方法的特徵簽名是一樣的。
3).所以即使Hero沒有顯式地提供fight()的定義,其定義也因ActionCharacter而隨之而來。
4).若把ActionCharacter的fight()改為private,就會出現提示說“類型 Hero必須實現繼承的抽象方法CanFight.fight()”的錯誤。
5).若把ActionCharacter的fight()改為private,就會出現提示說“繼承的方法 ActionCharacter.fight()不能隱藏CanFight中的公用抽象方法”的錯誤。
7、以上例子所展示的就是使用介面的核心原因:為了能夠向上轉型為多個基底類型。
8、使用介面的第二原因:與使用抽象基類相同,防止用戶端程式員建立該類的對象,並確保這僅僅是建立一個介面。
9、應該使用介面還是抽象類別:當要建立不帶任何方法定義和成員變數的基類時,使用介面。
10、事實上,如果知道某事物應該成為一個基類,那麼第一選擇應該是使它成為一個介面,只有在強制你必須具有方法定義和成員變數時,才應該選擇抽象類別,或者在必要時使其成為一個具體類。
11、介面通過繼承來擴充,如下:
interface Plant{ void grow();}interface Flower extends Plant{ void bloom();}interface Apple extends Plant, Flower{ void fruit();}class RedApple implements Apple{ public void grow(){ System.out.println("RedApple isgrowing."); } public void bloom(){ System.out.println("RedApple isblooming."); } public void fruit() { System.out.println("RedApple isfruiting."); }}
心細的人可能看到了Apple介面後extends Plant, Flower。一般情況下,只可以將extends用於單一類,但是既然介面可以由多個其它介面產生,那麼在建立一個新介面時,extends當然可以引用多個基類介面。此文法僅適用與介面的繼承。
12、Java中構建如同C++的enum類型那樣具備型別安全(變數的取值被限定在一個有限的範圍內):
public final class Month{ private String name; //private構造器,無法建立它的任何執行個體,所有執行個體都是在類的內部有其身建立的finalstatic執行個體 private Month(String name){ this.name = name; } public String toString(){ return name; } public static final Month JAN = new Month("January"), FEB = new Month("February"), MAR = new Month("March"), APR = new Month("April"), MAY = new Month("May"), JUN = new Month("June"), JUL = new Month("July"), AUG = new Month("August"), SEP = new Month("September"), OCT = new Month("October"), NOV = new Month("November"), DEC = new Month("December"); public static final Month[] month = { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC }; public static final Month number(int order){ return month[order - 1]; } public static void main(String[] args){ //curMonth是一個Month對象,它僅可以被賦予一個Month對象。這就體現了型別安全。 Month curMonth = Month.JAN; System.out.println(curMonth); curMonth = Month.number(12); System.out.println(curMonth); //這種方式同樣也允許你可互換地使用==或equal(),因為Month的每一個值都僅有一個執行個體。 System.out.println(curMonth == Month.DEC); System.out.println(curMonth.equals(Month.DEC)); System.out.println(Month.month[3]); }}
運行結果:
13、介面可以嵌套在類或其他介面中。嵌套介面可以擁有public和“包訪問”兩種可視性。同時,public和包訪問的嵌套介面都可以被實現為public、包訪問以及private的嵌套類。
class A{ interface B{ void fromB(); } interface D{ void fromD(); } //嵌套介面可以是private存取權限。 //它帶來的好處是:強制介面中的方法定義不要添加任何類型資訊(也就是說,不允許向上轉型),不明白,請看看最後的解說。 private interface I{ void fromI(); } //private的嵌套介面可以被實現為private private class J implements I{ public void fromI() { System.out.println("E.J.fromI()"); } } //private的嵌套介面也可以被實現為public public class J1 implements I{ public void fromI() { System.out.println("E.J1.fromI()"); } } //結合getI()和setI()方法實現“向上轉型”?! public I getI(){ return new J1(); } public void setI(I i){ i.fromI(); } //介面之間可以嵌套,嵌套在另一個介面中的介面只能是public的 interface K{ interface L{//此處也預設是public的 void fromL(); } }}public class E implements A.D{ public void fromD() { System.out.println("E.fromD()"); } //內部類F public public class F implements A.B{ public void fromB() { System.out.println("E.F.fromB()"); } } //內部類G protected protected class G implements A.B{ public void fromB() { System.out.println("E.G.fromB()"); } } //內部類I private private class H implements A.B{ public void fromB() { System.out.println("E.I.fromB()"); } } public static void main(String[] args){ E e = new E(); e.fromD(); //內部的執行個體化 E.F f = e.new F(); f.fromB(); E.G g = e.new G(); g.fromB(); E.H h = e.new H(); h.fromB(); //"實現了private介面I"的"public類J1"的執行個體化。 A.J1 j1 = new A().new J1(); j1.fromI(); A a = new A(); //A.I i = a.getI();//類型 A.I 不可視 //A.J1 j = a.getI();//不能從 A.I轉換為 A.J1 //a.getI().fromI();//類型 A.I 不可視 a.setI(a.getI()); }}
運行結果:
getI(),返回private介面的引用的public方法。在main()中,數次使用傳回值的行為都失敗了。只有一種方式可以成功,那就是將傳回值交給有權使用它的對象。在上例中,是一個A的對象a同過setI()方法來實現的。
以上內容整理自《Java編程思想》,如有遺漏,請您不吝指出!