Java中的介面和抽象類
一、介紹
抽象類:被abstract修飾的類就可以稱為抽象類。抽象類可以擁有抽象方法,也就是用abstract修飾的方法,這類方法沒有具體的實現結構,只是一個定義。
介面:用interface替換掉class形成的一個類似類的結構,接口裡面的方法全是抽象方法,介面本身不實現任何功能。
二、抽象類
抽象類本質還是一個類,它只是多了一個特點就是可以在抽象類裡面定義抽象方法,此外抽象類不能被例項化,也就是不能建立一個執行型別位抽象類的物件,看下面的例子:
1 class ceshi{ 2 public static void main(String[] args) { 3animal a1 = new animal();//報錯 4 Dog a3 = new Dog(); 5 a3.run(); 6 } 7 } 8 abstract class animal{ 9 public void speak() { 10 System.out.println("this is an animal"); 11 } 12 public abstract void run(); 13 } 14 class Dog extends animal{ 15 @Override16 public void run() { 17 System.out.println("Dog is running"); 18 } 19 }
可以看到animal是一個抽象類,它有一個抽象方法run,Dog類繼承了抽象類animal,並且實現了抽象方法run,這裡有幾點要注意的:
1、抽象類animal中可以有自己已經實現的方法,如第9行的speak方法,繼承抽象類animal的Dog類的物件是可以直接呼叫這個speak方法,這與普通的繼承相同。Dog也可以自己重寫這個speak方法。
2、抽象類中是可以沒有抽象方法的,編譯器不會報錯,但如果有抽象方法,繼承這個抽象類的普通類必須實現所有的抽象方法,不然會報錯。如果不實現,也可以將自己也定義為抽象類。
3、抽象類是不能被例項化的,也就是說它不能出現在new的後面,編譯器不能為一個抽象類來分配空間。上例第三行的報錯:
很明確的說明了被abstract修飾的抽象類是無法例項化的。
三、介面
《java程式設計思想》中有這樣一句話:“interface關鍵字使抽象的概念更向前邁進了一步”。
在介面中任何方法都是抽象的,介面這個關鍵字產生了一個完全抽象的類,它根本不提供任何具體實現(上文抽象類允許擁有自己的視線方法),只允許建立者確定方法名、引數列表和返回型別。一個介面就可以讓所有實現它的類看起來似乎都是一致的。
我們同樣看一個例子:
1 class ceshi{ 2 public static void main(String[] args) { 3 animal a1 = new animal();//報錯 4 Dog a3 = new Dog(); 5 a3.speak(); 6 } 7 } 8 9 interface animal{ 10 public void speak() ; 11 public abstract void run(); 12 } 13 class Dog implements animal{ 14 public void speak() { 15 System.out.println("this is an Dog"); 16 } 17 @Override 18 public void run() { 19 System.out.println("Dog is running"); 20 } 21 22 }
可以看到,我把animal從一個抽象類轉成了介面,同樣由Dog類去實現(抽象類稱為繼承)這個介面,同樣有幾個點需要關注:
1、接口裡面的方法前面其實預設有三個關鍵詞:abstract、static、final,這三個是在介面中無條件存在的,所以注意第10行和11行的對比,11行的abstrct是冗餘的,而我編譯器也貼心的提醒我:
2、實現了介面的類同樣也必須實現其中的抽象方法,而接口裡面的方法都是抽象的,所以你必須實現接口裡定義的全部方法。
3、介面中只能有抽象方法,不允許有方法體的方法。
4、同樣介面也是不能例項化的,也就是第三行的報錯,看一下報錯的原因:
這可能有點熟悉,當我們嘗試著去例項化抽象類的時候也是這樣的提示,說明介面其實也是預設為一個抽象類,只不過它抽象的更加徹底。
那介面中可以存在常量嘛?其實是可以的:
1 public static void main(String[] args) { 2 System.out.println(animal.x); 3 } 4 5 interface animal{ 6 int x = 0; 7 public void speak() ; 8 public abstract void run(); 9 }
拿這個例子來說,我在animal接口裡定義了一個常量,雖然我只是定義了它,但同上文所說,x是一個被static和final預設修飾了的靜態變數(abstract只能修飾方法和類),所以我能在主函式中利用介面的名字去呼叫x的值,這與普通類中的靜態變數是相似的,介面同樣有其靜態儲存空間,靜態變數就說儲存在裡面。
三、介面和抽象類的對比
最後貼一個總結:
11