Java中封裝的實(shí)現(xiàn),是通過為私有成員提供訪問器方法,即通常所知的getter和setter方法。這樣封裝是否合適仍屬爭(zhēng)議,也超出了本文的討論范圍。但是,當(dāng)成員變量為集合類型(java.util.Collection,java.util.Map以及它們的子類)時(shí),這樣實(shí)現(xiàn)封裝是完全錯(cuò)誤的。
我經(jīng)常能見到的代碼像下面這樣:
就我所見,這樣的代碼很普遍,這是由于Hibernate等ORM框架使得這種設(shè)計(jì)變得流行。很多時(shí)候,當(dāng)我提出我的觀點(diǎn),得到的建議就是使用一種不可變的設(shè)計(jì):
不合適的封裝
然而,在使用集合類型的情形下,由于Java中集合類型自身是可變的,這其實(shí)并沒有任何改變。很明顯,無論是通過構(gòu)造函數(shù)傳入一個(gè)集合實(shí)例的引用,還是返回它的引用,這完全沒有進(jìn)行封裝。只有當(dāng)集合實(shí)例的引用沒有(在外部)保留,也不會(huì)返回(到外部),真正的封裝才有可能實(shí)現(xiàn)。
不能使用具體的子類
另外,MyBean類可能需要封裝一種更具體的集合類,比如List或者Set。從下面的代碼片段可以看出,傳入一個(gè)Set實(shí)例是不可能的。
不能選擇具體的實(shí)現(xiàn)
由上一點(diǎn)很自然地想到,使用(外部)提供的引用的話,我們也無法使用(可能為了更高效)自己定義的類,比如Apache Commons的FastArrayList。
實(shí)現(xiàn)建議
下面的代碼做到了真正封裝的出發(fā)點(diǎn)。
這種方式解決了前面提到的幾個(gè)問題:
集合實(shí)例的引用沒有從構(gòu)造函數(shù)中傳入,這樣就不可能在實(shí)例外部改變實(shí)例。
由于完全隔離,可以自由地選擇集合的實(shí)現(xiàn),為修改留下余地。
不能通過getter訪問器方法獲得被封裝的集合實(shí)例的引用。
注意:為了可讀性,前面的代碼片段沒有使用泛型。請(qǐng)?jiān)趯?shí)際使用中加上。
以上就是北大青鳥長(zhǎng)沙麓谷校區(qū)java培訓(xùn)機(jī)構(gòu)的小編針對(duì)“基礎(chǔ)內(nèi)容分享:Java封裝練習(xí)題”的內(nèi)容進(jìn)行的回答,希望對(duì)大家有所幫助,如有疑問,請(qǐng)?jiān)诰€咨詢,有專業(yè)老師隨時(shí)為你服務(wù)。