本文實例講述了Java中構(gòu)造器內(nèi)部的多態(tài)方法的行為操作。分享給大家供大家參考,具體如下:
公司主營業(yè)務:網(wǎng)站設(shè)計、網(wǎng)站制作、移動網(wǎng)站開發(fā)等業(yè)務。幫助企業(yè)客戶真正實現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)是一支青春激揚、勤奮敬業(yè)、活力青春激揚、勤奮敬業(yè)、活力澎湃、和諧高效的團隊。公司秉承以“開放、自由、嚴謹、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團隊有機會用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)推出荷塘免費做網(wǎng)站回饋大家。
這篇文章主要討論的是,若在一個構(gòu)造器中調(diào)用正在構(gòu)造的對象的某個動態(tài)綁定的方法時會出現(xiàn)的情況。在此之前,我們需要知道構(gòu)造器是如何在復雜的層次結(jié)構(gòu)中運作的,盡管構(gòu)造方法并不具有多態(tài)性,因為它們實際上是static方法,只不過是隱式聲明的static。
復雜層次結(jié)構(gòu)中構(gòu)造器的調(diào)用順序
基類的構(gòu)造器總是在導出類的構(gòu)造過程中被調(diào)用,而且按照繼承層次逐漸向上鏈接,以使每個基類的構(gòu)造器都能得到調(diào)用。這樣做是因為,在Java類中,我們通常將字段設(shè)置為private類型,也就是說,在子類中通常無法直接訪問基類的字段,那么只有通過調(diào)用基類的構(gòu)造器才能對基類對象的元素進行初始化,那么就必須保證所有的構(gòu)造器都得到調(diào)用,這樣才能正確地構(gòu)造完整的對象。下面的例1展示了包含有組合與繼承關(guān)系的各類中構(gòu)造器的調(diào)用順序:
例1:
class Meal { Meal() { System.out.println("Meal()"); } } class Bread { Bread() { System.out.println("Bread()"); } } class Cheese { Cheese() { System.out.println("Cheese()"); } } class Lettuce { Lettuce() { System.out.println("Lettuce()"); } } class Lunch extends Meal { Lunch() { System.out.println("Lunch()"); } } class PortableLunch extends Lunch { PortableLunch() { System.out.println("PortableLunch()");} } public class Sandwich extends PortableLunch { private Bread b = new Bread(); private Cheese c = new Cheese(); private Lettuce l = new Lettuce(); public Sandwich() { System.out.println("Sandwich()"); } public static void main(String[] args) { new Sandwich(); } }
例1反映了關(guān)于Meal、Lunch和Sandwich之間三層繼承關(guān)系(不包含Object類),以及Bread、Cheese和Lettuce與Sandwich的組合關(guān)系。在main函數(shù)中創(chuàng)建一個Sandwich對象后,我們就可以看到輸出結(jié)果:
這說明在復雜的層次結(jié)構(gòu)中構(gòu)造器的調(diào)用遵從的順序為:
** 1、調(diào)用基類構(gòu)造器。這個步驟會不斷地反復遞歸下去,首先是構(gòu)造這種層次結(jié)構(gòu)的根,然后是下一層導出類,等等,直到最低層的導出類;
2、按聲明的順序調(diào)用成員的初始化方法;
3、調(diào)用導出類構(gòu)造器的主體。**
構(gòu)造器內(nèi)部的多態(tài)方法的行為
那么,現(xiàn)在我們回到文章開頭提到的問題,若在一個構(gòu)造器中調(diào)用正在構(gòu)造的對象的某個動態(tài)綁定的方法,會出現(xiàn)什么情況呢?我們知道,動態(tài)綁定(或后期綁定)的方法的調(diào)用是在運行時才決定的,因為對象在程序運行之前無從得知它自己到底是基類的對象,還是某個導出類的對象。如果在基類的構(gòu)造器內(nèi)部調(diào)用某個動態(tài)綁定方法,該方法是被導出類覆蓋的,那么這便可能產(chǎn)生難以預料的后果,因為該導出類的對象還未被完全構(gòu)造,但它的方法卻被調(diào)用了。我們可以通過例2看到問題所在:
例2:
class Glyph { void draw() { System.out.println("Glyph.draw()"); } Glyph() { System.out.println("Glyph() before draw()"); draw(); System.out.println("Glyph() after draw()"); } } class RoundGlyph extends Glyph { private int radius = 1; RoundGlyph(int r) { radius = r; System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius); } void draw() { System.out.println("RoundGlyph.draw(), radius = " + radius); } } public class PolyConstructors { public static void main(String[] args) { new RoundGlyph(5); } }
運行結(jié)果:
在運行結(jié)果中,我們看到,基類Glyph的構(gòu)造器中調(diào)用了被子類RoundGlyph覆蓋的draw()方法,并且輸出了radius=0,這顯然是一個錯誤,因為這個“0”是在其他任何事物發(fā)生之前,系統(tǒng)分配給對象的存儲空間的初始值——二進制的零,而非我們想要設(shè)定的初始值“1”。這是因為,我們在創(chuàng)建子類(RoundGlyph)對象時會先調(diào)用基類(Glyph)的構(gòu)造器構(gòu)造基類對象,而在基類的構(gòu)造器中卻調(diào)用了被子類覆蓋的動態(tài)綁定的方法(draw()),而這個方法所操縱的可能是子類中的還未進行初始化的成員(radius),這便會招致災難,盡管編譯器并沒有報錯。
因此,在編寫構(gòu)造器中有一條有效的準則:“用盡可能簡單的方法使對象進入正常狀態(tài);如果可以的話,避免調(diào)用其他方法”。在構(gòu)造器中,唯一能夠安全調(diào)用的是基類中的final方法(包括private方法),因為這些方法不能被子類覆蓋,也就不會出現(xiàn)上述的問題。
更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java面向?qū)ο蟪绦蛟O(shè)計入門與進階教程》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設(shè)計有所幫助。
當前名稱:Java中構(gòu)造器內(nèi)部的多態(tài)方法的行為實例分析
網(wǎng)站網(wǎng)址:http://muchs.cn/article26/pjjdjg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、網(wǎng)站維護、ChatGPT、虛擬主機、網(wǎng)站營銷、用戶體驗
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)