用最簡單的話來講,一個抽象類就是使用keyword聲明爲abstract的abstract
。它可能包含也可能不包含任何抽象方法。JVM將抽象類標識爲不完整類,該類還沒有定義其完整行爲。聲明一個類abstract
僅強制執行一件事:您不能建立此類的實例,僅此而已。
那麼,爲何還要費心建立一個根本沒法實例化的類呢?答案在於解決某些關鍵設計問題的方法。咱們將在本文後面介紹這一部分。
html
abstract class TestAbstractClass { public abstract void abstractMethod(); public void normalMethod() { //method body } }
在這裏,咱們TestAbstractClass
有兩種方法,一種是抽象方法,第二種是普通方法。抽象方法。在類中使用抽象方法將迫使您將類聲明爲抽象自己。
java
一個抽象方法,是未取代實施的方法。抽象方法給類增長了不完整性,所以編譯器但願將整個類聲明爲抽象。
在應用程序中使用抽象類的惟一方法是擴展此類。若是不abstract
再次聲明其子類,則能夠實例化。子類繼承了超類的行爲,而且超類能夠保留對子類的引用的功能在不少方面增長了抽象類的重要性。
python
接口是大多數Java API的另外一個基本構建塊。您將其命名爲collection,I / O或SWT,您能夠在任何地方看到它們的運行狀況。程序員
接口定義合同,實現類須要遵照這些合同。api
這些合同本質上是未實現的方法。Java已經有一個未實現方法的關鍵字,即_abstract_。Java規定任何類均可以實現任何接口,所以在接口中聲明的全部方法僅需是公共的。
oracle
public interface TestInterface { void implementMe(); }
對於上述接口,任何實現類都須要重寫implementMe()
方法。
框架
當實現一個接口而且不重寫該方法即聲明實現類自己時,只有一種狀況abstract
。
抽象類ide
public abstract class TestMain implements TestInterface { //No need to override implement Me }
不然,您必須implementMe()
在您的類中實現該方法,而沒有任何其餘例外。
非抽象類學習
public class TestMain implements TestInterface { @Override public void implementMe() { // TODO Auto-generated method stub } }
讓咱們記下抽象類和接口之間的差別以便快速查看:ui
extends
,而爲了實現接口關鍵字是implements
。一個類只能擴展一個類,但能夠實現任何數量的接口。在Java中,此屬性一般稱爲多重繼承的模擬。abstract
,不能實例化;Java抽象類也沒法實例化,可是若是存在main()則能夠調用它。接下來,若是咱們既有抽象方法又有主類,可能會有一個問題,咱們能夠嘗試從中調用抽象方法main()
。可是這種嘗試將失敗,由於main()
方法始終是靜態的,而抽象方法永遠不會是靜態的,所以您永遠沒法訪問靜態方法內部的任何非靜態方法。
始終記住,在接口或抽象類之間進行選擇既不是/也不是方案,在這種狀況下,選擇未經適當分析的任何人都會產生相同的結果。瞭解當前問題後,必須很是明智地作出選擇。讓咱們嘗試在這裏添加一些智慧。
抽象類使您能夠定義一些行爲。它使它們成爲應用程序框架內的優秀候選人。
讓咱們以HttpServlet爲例。若是要使用Servlets技術開發Web應用程序,則必須繼承該類。衆所周知,每一個servlet都有明確的生命週期階段,即初始化,服務和破壞。若是咱們建立了每一個servlet,咱們必須一次又一次地編寫關於初始化和銷燬的同一段代碼。固然,這將是一個很大的痛苦。
JDK設計人員經過製做HttpServlet
抽象類來解決此問題。它具備爲初始化Servlet和銷燬Servlet而編寫的全部基本代碼。您只須要重寫某些方法便可在其中編寫與應用程序處理相關的代碼。有道理吧!
可使用界面添加上述功能嗎?不,即便能夠,對於大多數無辜的程序員來講,設計也將是一個地獄。
如今,讓咱們看一下接口的用法。接口僅提供合同,實現類的責任是實現提供給它的每一個合同。
若是隻想定義class的特徵,而且要強制全部實現實體實現這些特徵,那麼接口是最合適的。
我想以Map
集合框架中的接口爲例。它僅提供規則,以及map在實踐中應如何表現。例如,它應存儲鍵值對,應使用鍵等訪問該值。這些規則在接口中採用抽象方法的形式。
全部實現類(例如HashMap,HashTable,TreeMap或WeakHashMap)均以不一樣方式實現全部方法,所以與其餘方法相比具備不一樣的功能。
一樣,接口可用於定義職責分離。例如,HashMap
實現3個接口:Map
,Serializable和Cloneable。每一個接口定義了各自的職責,所以實現類選擇要實現的對象,所以將提供有限的功能。
使用Java 8,您如今能夠在接口中定義方法。這些稱爲默認方法。默認方法使您能夠向庫的接口添加新功能,並確保與爲這些接口的較早版本編寫的代碼二進制兼容。
顧名思義,Java 8中的默認方法就是默認的。若是不重寫它們,則它們是調用方類將調用的方法。
默認方法
public interface Moveable { default void move(){ System.out.println("I am moving"); } }
在上面的示例中,Moveable
接口定義了一種方法,move()
而且還提供了默認實現。若是有任何類實現此接口,則無需實現它本身的move()
方法版本。它能夠直接調用instance.move()
。
public class Animal implements Moveable{ public static void main(String[] args){ Animal tiger = new Animal(); tiger.move(); //I am moving } }
而且,若是類願意定製行爲,那麼它能夠提供本身的定製實現並重寫該方法。如今將調用它本身的自定義方法。
public class Animal implements Moveable{ public void move(){ System.out.println("I am running"); } public static void main(String[] args){ Animal tiger = new Animal(); tiger.move(); //I am running }
若是您看到了,咱們如今也能夠提供帶有接口的部分實現,就像抽象類同樣。所以,從本質上說,接口與抽象類之間的界限變得很是狹窄。它們如今提供幾乎相同的功能。
如今,只有一個很大的不一樣,即您不能擴展多個類,而能夠實現多個接口。除了這種差別以外,您還能夠經過接口實現任何可能的功能,這些接口可使抽象類成爲可能,反之亦然。
但願您在Java中找到有關接口和抽象類的足夠信息。
學習愉快!
更多精彩請關注公衆號【lovepythoncn】