前面介紹了多態的相關用法,能夠看到一個子類從父類繼承以後,便能假借父類的名義處處晃悠。這種機制在正常狀況之下沒啥問題,但有時爲了預防意外發生,每每只接受當事人來處理,不但願它的兒子乃至孫子來瞎摻和。但是猶記得幾種開放性修飾符,只能控制某個實體可否被外部訪問,從未據說可決定某個類可否被其它類所繼承。
毫無疑問,是否開放與可否繼承是兩種不一樣的概念,不論是被public修飾的公共類,仍是被private修飾的私有類,它們默認都是容許繼承的。要想讓某個類不能被其它類繼承,還得在類名前面額外添加一個關鍵字final,表示這個類已是最終的類,請不要再去派生子類了。相對多態概念而言,final也能夠理解爲終態,即最終的狀態,終態固然是不可改變的,不然就不叫終態了。
仍舊以雞類爲例,長大之後的雞很容易區分是公雞仍是母雞,不論是從雞冠仍是羽毛仍是叫聲,都能迅速分辨公雞母雞。可是對於小雞來講,區分它的性別可不容易,要知道有一種職業叫作「小雞性別鑑定師」,年薪高達4萬英鎊(摺合人民幣40萬左右)。因此,與其花費九牛二虎之力去分辨小雞的性別,不如直接忽略它們的區別,反正看起來都是一羣毛茸茸的小傢伙麼。既然小雞再也不區別性別,那麼小雞類就無需派生什麼公小雞、母小雞之類,如此一來,新定義的小雞類必須是最終狀態的類,不可被其它類繼承。在一個類定義的最前面添加final修飾符,該類就變成了終態類,因而保持終態的小雞類Chick的定義代碼示例以下:html
//定義一個小雞類。由於小雞的性別難以辨別,因此再也不定義性別字段,小雞類也不容許被繼承 final public class Chick { // 定義一個名稱屬性 public String name; // 定義一個叫喚方法 public void call() { System.out.println("嘰嘰喳喳"); } }
上面的Chick類,與普通類的區別僅僅是多了個final,正由於有了final,它才成爲無兒無女的終類。java
關鍵字final除了用於修飾類,還能用來修飾類的成員屬性和成員方法。當一個成員屬性戴上了final的帽子,它就必須在變量聲明的同時一塊賦值,而且這個初始值也是該屬性的終值。凡是被final修飾的成員屬性,只能進行初始化賦值,過後不能再次給它賦值了。要是一個成員方法也戴上final的帽子,意味着該方法是最終方法,不可在子類中重寫,即便它是public類型也無濟於事。
總的來講,final存在的意義是爲了維護某個實體的純潔性,不容許外部肆意篡改該實體。下列是final可做用的實體及其產生的影響:
一、一旦某個類被final修飾,則該類沒法再派生出任何子類。
二、一旦某個成員屬性被final修飾,則該屬性不能再次賦值了。
三、一旦某個成員方法被final修飾,則該方法禁止被子類重載。
接下來嘗試給雞類增長几個終態的final成員,原先在公雞類中使用數字0表示雄性,在母雞類中使用數字1表示雌性,顯然數字取值很容易搞混淆。如今利用兩個終態的整型變量MALE和FEMALE分別保存0和1,因爲終態屬性沒法被再次修改,所以這兩個變量形同常量。具體的性別常量定義代碼以下所示:htm
// 如下利用final修飾成員屬性和成員方法 public final int MALE = 0; // 雄性 public final int FEMALE = 1; // 雌性
假如Chicken原來有個canSwim方法,考慮到雞類都不會游泳,那麼該方法確定返回false。故而canSwim方法徹底能夠披上final的護身符,無論公雞類仍是母雞類,都不能重寫該方法。因而包含終態屬性和終態方法的雞類定義代碼變成了下面這樣:blog
//定義一個雞類 public class Chicken { // 定義一個名稱屬性 public String name; // 定義一個性別屬性 public int sex; // 定義一個叫喚方法 public void call() { System.out.println("半夜雞叫"); } // 如下利用final修飾成員屬性和成員方法 public final int MALE = 0; // 雄性 public final int FEMALE = 1; // 雌性 // 定義一個可否游泳的方法 public final boolean canSwim() { return false; } }
對於外部來講,訪問終態屬性和終態方法的方式沒有改變,仍然是以「實例名稱.成員名稱」的形式。下面是外部調用新雞類的代碼例子:繼承
// 建立一個雞類的實例 Chicken chicken = new Chicken(); // Chicken類的MALE屬性是個終屬性,首次初始化後就不能再作修改 System.out.println("MALE="+chicken.MALE); // Chicken類的FEMALE屬性是個終屬性,首次初始化後就不能再作修改 System.out.println("FEMALE="+chicken.FEMALE); // Chicken類的canSwim方法是個終方法,子類不能重寫該方法 System.out.println("Chicken canSwim="+chicken.canSwim());
更多Java技術文章參見《Java開發筆記(序)章節目錄》開發