面向對象的編程容許從已經存在的類中定義新的類,這稱爲繼承。java
面向過程的範式重點在於方法的設計,而面向對象的範式將數據和方法結合在對象中。面向對象範式的軟件設計着重於對象以及對象上的操做。面向對象的方法結合了面向過程範式的強大之處,而且進一步將數據和操做集成在對象中。編程
繼承可使得你能夠定義一個通用的類(即父類),以後擴充該類爲一個更加特定的類(即子類)。在Java術語中,若是類C1擴展自另外一個類C2,那麼就將C1稱爲次類,將C2稱爲超類。 超類也稱爲父類或基類,次類又稱爲子類、拓展類或派生類。數組
子類從它的父類中繼承可訪問的數據域和方法,還能夠添加新數據域和新方法。安全
若是父類中有私有的數據域,這個類被繼承後,父類中的私有數據域是不能被子類訪問的,惟一能讀取和改變它們的方法就是經過它們的get和set方法。測試
和傳統的理解不一樣,子類並非父類的一個子集。實際上,一個子類一般比它的父類包含更多的信息和方法。ui
父類中的私有數據域在該類以外是不可訪問的。所以,不能在子類中直接使用。可是,若是父類中定義了公共的訪問器/修改器方法,那麼能夠經過這些公共的訪問器/修改器來訪問和修改它們。設計
不是全部的「是一種」關係都該用繼承來建模。繼承是用來爲「是一種」關係建模的。不要僅僅爲了重用方法這個緣由而盲目地擴展一個類。對象
某些程序設計語言是容許從幾個類派生出一個子類的。這種能力成爲多重繼承。可是在Java中是不容許多重繼承的。一個Java類只可能直接繼承自一個父類。這種限制稱爲單一繼承。若是使用extends關鍵字來定義一個子類,它只容許有一個父類。然而,多重繼承是能夠經過接口來實現的。繼承
關鍵字super指代父類,能夠用於調用父類中的普通方法和構造方法。接口
構造方法用於構建一個類的實例。不一樣於屬性和普通方法,父類的構造方法不會被子類繼承。它們只能使用關鍵字super從子類的構造方法中調用。調用父類構造方法的語法是:super(),或者super(parameters);語句super()調用父類的無參構造方法,而語句super(arguments)調用與參數匹配的父類的構造方法。語句super()和super(arguments)必須出如今子類構造方法的第一行,這是顯示調用父類構造方法的惟一方式。
要調用父類的構造方法就必須使用關鍵字super,並且這個調用必須是構造方法的第一條語句。在子類中調用父類構造方法的名字會引發一個語法錯誤。
構造方法能夠調用重載的構造方法或父類的構造方法。若是它們都沒有被顯示地調用,編譯器就會自動地將super()做爲構造方法的第一條語句。
子類必須使用super調用父類的構造方法,若是沒有顯示調用的話,就會使用super(),調用父類不帶參數的構造方法,若是父類沒有不帶參數的構造方法,則必須顯示地用帶參數的super(parameters)調用父類的構造方法。
通常狀況下,最好能爲每一個類提供一個無參構造方法,以便於對該類進行擴展,同時避免錯誤。
在任何狀況下,構造一個類的實例時,將會調用沿着繼承鏈的全部父類的構造方法。當構造一個子類的對象時,子類構造方法會在完成本身的任務以前,首先調用它的父類的構造方法。若是父類繼承自其餘類,那麼父類構造方法又會在完成本身的任務以前,調用它本身的父類的構造方法。這個過程持續到沿着這個繼承體系結構的最後一個構造方法被調用爲止。這就是構造方法鏈。
關鍵字super不只能夠引用父類的構造方法,還能夠引用父類的方法。
子類從父類中繼承方法。有時,子類須要修改父類中定義的方法的實現,這稱做方法重寫。
方法重寫:要重寫一個方法,須要在子類中使用和父類同樣的簽名以及同樣的返回值類型來對該方法進行定義。
僅當實例方法是可訪問的,它才能被覆蓋。由於私有方法在它自己之外是不能訪問的,因此它不能被覆蓋。若是子類中定義的方法在父類中是私有的,那麼這兩個方法徹底沒有關係。
與實例方法同樣,靜態方法也能被繼承。可是,靜態方法不能被覆蓋。若是父類中定義的靜態方法在子類中被從新定義,那麼在父類中定義的靜態方法將被隱藏。可使用語法:父類名.靜態方法名調用隱藏的靜態方法。
重載意味着使用一樣的名字可是不一樣的簽名來定義多個方法。重載意味着在子類中提供一個對方法的新的實現。
方法重寫發生在經過繼承而相關的不一樣類中;方法重載能夠發生在同一個類中。也能夠發生在因爲繼承而相關的不一樣類中。
方法重寫具備一樣的簽名和返回值類型;方法重載具備相同的名字,可是不一樣的參數列表。
重載方法使得可使用一樣的名字來定義不一樣方法,只要它們的簽名是不一樣的。(方法名和參數列表共同構成方法簽名,這裏方法名相同,則重載方法要求參數列表不一樣。)
被重載的方法必須具備不一樣的參數列表。不能基於不一樣修飾符或返回值類型來重載方法。
Java中的全部類都繼承自java.lang.Object類。
若是在定義一個類時沒有指定繼承性,那麼這個類的父類就被默認爲是Objec。
多態意味着父類的變量能夠指向子類對象。
面向對象程序設計的三大支柱是封裝、繼承和多態。
一個類實際上定義了一種類型。子類定義的類型稱爲子類型,而父類定義的類型稱爲父類型。
繼承關係使一個子類繼承父類的特徵,而且附加一些新特徵。子類是它的父類的特殊化,每一個子類的實例都是其父類的實例,可是反過來就不成立。例如:每一個圓都是一個幾何對象,但並不是每一個幾何對象都是圓。
使用父類對象的地方均可以使用子類對象,這就是一般所說的多態。簡單來講,多態意味着父類型的變量能夠引用子類型的對象。
動態綁定:方法能夠在沿着繼承鏈的多個類中實現,JVM決定運行時調用哪一個方法。
聲明類型和實際類型:一個變量必須被聲明爲某種類型。變量的這個類型稱爲它的聲明類型。一個引用類型變量能夠是一個null值或者是一個對聲明類型實例的引用。實例可使用聲明類型或它的子類型的構造方法建立。變量的實際類型是被變量引用的對象的實際類。
動態綁定工做機制以下:假設對象o是類C1的實例,存在類C1,C2,...,Cn-1,Cn,其中C1是C2的子類,C2是C3的子類,...,Cn-1是Cn的子類,也就是說,Cn是最通用的類,C1是最特殊的類。在Java中,Cn是Object類。若是對象o調用一個方法p,那麼JVM會依次在類C1,C2,...,Cn-1,Cn中查找方法p的實現,直到找到爲止,一旦找到一個實現,就中止查找,而後調用這個首先找到的實現。
匹配方法的簽名和綁定方法的實現是兩個不一樣的問題。引用變量的聲明類型決定了編譯時匹配哪一個方法。在編譯時,編譯器會根據參數類型、參數個數和參數順序找到匹配的方法。一個方法可能在沿着繼承鏈的多個類中實現。Java虛擬機在運行時動態綁定方法的實現,這是由變量的實際類型決定的。
對象的引用能夠類型轉換爲對另外一種對象的引用,這稱爲對象轉換。
Object o = new Student();
因爲Student的實例也是Object的實例,因此,語句Object o=new Student()是合法的,它稱爲隱式轉換。
假設通過上面的一步想使用下面的語句把對象引用o賦值給Student類型的變量:
Student b=o;
這種狀況下,將會發生編譯錯誤。由於Student對象老是Object的實例,可是,Object對象不必定是Student的實例。即便能夠看到o其實是一個Student對象,可是編譯器尚未聰明到知道這一點。爲了告訴編譯器o就是一個Student對象,就要使用顯示轉換。它的語法與基本類型轉換的語法很相似,用圓括號把目標對象的類型括住,而後放到要轉換的對象前面:
Student b = (Student)o;
老是能夠將一個子類的實例轉換爲一個父類的變量,稱爲向上轉換,由於子類的實例永遠是它的父類實例。
當把一個父類的實例轉換爲它的子類變量(稱爲向下轉換)時,必須使用轉換記號「(子類名)」進行顯示轉換,向編譯器代表意圖。爲使轉換成功,必須確保要轉換的對象是子類的一個實例。若是父類對象不是子類的一個實例,就會出現一個運行異常ClassCastException。例如:若是一個對象不是Student的實例,它就不能轉換成Student類型的變量。所以,一個好的經驗是,在嘗試轉換以前確保該對象是另外一個對象的實例。這是能夠利用instanceof來實現的。
聲明類型決定了在編譯時匹配哪一個方法。
爲了更好地理解類型轉換,能夠認爲它們相似於水果、蘋果、橘子之間的關係,其中水果類Fruit是蘋果類Apple和橘子類Orange的父類。蘋果是水果,因此,老是能夠將Apple的實例安全地賦值給Fruit變量。可是,水果不必定是蘋果,因此必須進行顯示轉換才能將Fruit的實例賦值給Apple變量。
比較運算符==用來比較兩個基本數據類型的值是否相等,或者判斷兩個對象是否具備相同的引用。若是想讓equals方法可以判斷兩個對象是否具備相同的內容,能夠在定義這些對象時,重寫equals方法。
ArrayList對象能夠用於存儲一個對象列表:以前能夠建立一個數組存儲對象,可是這個數組一旦建立,它的大小就固定了。Java提供ArrayList類來存儲不限定個數的對象。ArrayList是一種泛型類,具備一個泛型類型E。建立一個ArrayList時,能夠指定一個具體的類型來替換E。
ArrayList<AConcreteType> list = new ArrayList<AConcreteType>();能夠簡化爲:
ArrayList<AConcreteType> list = new ArrayList<>();
要建立一個用於存儲整數的ArrayList,因爲存儲在ArrayList中的元素必須是一種對象,因此不能使用諸如int的基本類型來替代一個泛型類型,可使用以下的聲明方式:
ArrayList<Integer> list = new ArrayList<>();
ArrayList的大小是靈活的,因此無須提早給定它的大小。而當建立一個數組時,它的大小必須給定。
ArrayList包含許多有用的方法。好比contains方法來測試某個元素是否在列表中。
一個類中的受保護成員能夠從子類中訪問。
私有成員只能在類內訪問,而共有成員能夠被任意的其餘類訪問。
常常須要容許子類訪問定義在父類中的數據域和方法,但不容許非子類訪問這些數據域和方法。可使用關鍵字protected完成該功能。父類中被保護的數據域和方法能夠在它的子類中訪問。
使用private修飾符能夠徹底隱藏類的成員,這樣,就不能從類外直接訪問他們。不使用修飾符就表示容許同一個包裏的任何類直接訪問類的成員,可是其餘包中的類不能夠訪問。使用protected修飾符容許任何包中的子類或同一包中的類訪問類的成員。使用public修飾符容許任意類訪問類的成員。
類能夠以兩種方式使用,一種是用於建立該類的實例;另外一種是經過擴展該類建立它的子類。若是不想從類的外部使用類的成員,就把成員聲明成private。若是想讓該類的用戶都能使用類的成員,就把成員聲明成public。若是想讓該類的擴展者使用數據和方法,而不想讓該類的用戶使用,則把成員聲明成protected。
修飾符private和protected只能用於類的成員,public修飾符和默認修飾符既能夠用於類的成員,也能夠用於類。一個沒有修飾符的類是不能被其餘包中的類訪問的。
子類能夠重寫它的父類的protected方法,並把它的可見性改成public。可是,子類不能削弱父類中定義的方法的可訪問性。例如:若是一個方法在父類中定義爲public,在子類中也必須定義爲public。