復(fù)用代碼是 Java 眾多引人注目的功能之一。這句話很通順,沒什么問題,但問題在于很多人并不清楚“復(fù)用”是什么。就好像我說“沉默王二是一個(gè)有趣的程序員”,唉,沉默王二是誰(shuí)?
創(chuàng)新互聯(lián)于2013年創(chuàng)立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元沙市做網(wǎng)站,已為上家服務(wù),為沙市各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18982081108
我們需要來(lái)給“復(fù)用”下一個(gè)定義。復(fù)用,說白了就是重復(fù)使用。
舉個(gè)例子,很多名人說了很多名言,我們?cè)谡f話、寫作的時(shí)候,就經(jīng)常有意無(wú)意的重復(fù)這些名言。比如說我,就特別喜歡重復(fù)使用王小波的那句名言:“從話語(yǔ)中,你很少能學(xué)到人性,從沉默中卻能。假如還想學(xué)得更多,那就要繼續(xù)一聲不吭?!?/p>
上面這個(gè)例子,只能說是“復(fù)用”的一種低級(jí)的應(yīng)用,其實(shí)就是復(fù)制粘貼了。還有高級(jí)的復(fù)用方式嗎?
有,當(dāng)然有。Java 作為一種優(yōu)秀的面向?qū)ο笤O(shè)計(jì)的語(yǔ)言,在復(fù)用的應(yīng)用上就高級(jí)得多了。
最常見的復(fù)用方法就是繼承——使用 extends
關(guān)鍵字在基類的基礎(chǔ)上創(chuàng)建新類,新類可以直接復(fù)用基類的非 private
的屬性和方法;就像程序清單1-1那樣。
程序清單1-1:
public?class?Wangxiaosan?extends?Wangsan?{
????public?Wangxiaosan()?{
????????System.out.println("我是新類王小三");
????????setName("王老三");
????????System.out.println(getName());
????}
????public?static?void?main(String[]?args)?{
????????new?Wangxiaosan();
????}
}
class?Wangsan?{
????private?String?name;
????Wangsan()?{
????????System.out.println("我是基類王三");
????}
????public?String?getName()?{
????????return?name;
????}
????public?void?setName(String?name)?{
????????this.name?=?name;
????}
}
從程序清單 1-1 中我們可以看得出,getName() 和 setName() 方法雖然是在基類 Wangsan 中創(chuàng)建的,但可以在新類 Wangxiaosan 中使用,代碼的復(fù)用工作就這樣輕松地完成了。
另外一種常見的復(fù)用方法就是組合——在新類中創(chuàng)建已有類的對(duì)象,通過該對(duì)象來(lái)調(diào)用已有類中的非 private 的屬性和方法;就像程序清單2-1那樣。
程序清單2-1:
public?class?Tongxiangyu?{
????private?Baizhantang?boyFriend?=?new?Baizhantang();
????public?Tongxiangyu()?{
????????System.out.println("我是同??蜅5恼乒褓∠嬗?);
????????boyFriend.pointHand("郭芙蓉");
????}
????public?static?void?main(String[]?args)?{
????????new?Tongxiangyu();
????}
}
class?Baizhantang?{
????Baizhantang()?{
????????System.out.println("我是退隱江湖的盜圣白展堂");
????}
????public?void?pointHand(String?name)?{
????????System.out.println("那誰(shuí)"?+?name?+?",準(zhǔn)備一下——葵花點(diǎn)穴手");
????}
}
從程序清單 2-1 中我們可以看得出,葵花點(diǎn)穴手雖然是白展堂的絕技,但作為佟掌柜的男朋友,佟掌柜要展堂點(diǎn)個(gè)穴,展堂也是不敢推辭的。你看,佟掌柜雖然是個(gè)弱女子,但自從有了展堂這個(gè)武功數(shù)一數(shù)二的男朋友,再?zèng)]有誰(shuí)敢不聽話啊——厲害的組合啊。
需要注意的是,如何在繼承和組合之間做出選擇呢?
如果新類和已有類需要具有一些相似的方法和屬性時(shí),就采用繼承的形式;如果新類只是為了借用已有類的一些方法和屬性時(shí),而兩者沒有很多相似之處時(shí)就需要采用組合的形式。
還有一種復(fù)用方法是代理——在新類中創(chuàng)建代理,通過代理來(lái)操作已有類的非 private 的屬性和方法;就像程序清單 3-1 那樣。
程序清單3-1:
public?class?Member?{
????public?static?void?main(String[]?args)?{
????????Proxy?proxy?=?new?Proxy();
????????System.out.println("代理說一個(gè)藥丸十五塊");
????????proxy.buy(15);
????}
}
class?Proxy?{
????private?Shop?shop?=?new?Shop();
????public?void?buy(int?money)?{
????????System.out.println("一個(gè)藥丸十五塊");
????????shop.sale(money?-?5);
????}
}
class?Shop?{
????public?void?sale(int?money)?{
????????System.out.println("一個(gè)藥丸十塊錢");
????}
}
從程序清單 3-1 中我們可以看得出,代理的模式和組合有點(diǎn)類似,但又有差別——代理成功的隔開了新類(會(huì)員)和已有類(店鋪)的直接關(guān)系,使得已有類的方法不直接暴露在新類面前(組合的方式會(huì)將已有類的非private的方法和屬性直接暴露在新類中);與此同時(shí),代理拿到了足夠的好處。
作為代碼的生產(chǎn)者來(lái)說,我們有時(shí)候希望代碼被復(fù)用,有的時(shí)候又希望代碼不被復(fù)用。當(dāng)我們不想代碼被復(fù)用時(shí),final 關(guān)鍵字就派上用場(chǎng)了。final 這個(gè)關(guān)鍵字很形象,它本身就說明了一切——最后的,最終的;決定性的;不可更改的。
使用 final 的場(chǎng)景有三種,分別是數(shù)據(jù)、方法和類。我們來(lái)稍作說明。
1)final 數(shù)據(jù)
最常見的 final 數(shù)據(jù)就是常量了,例如:
public?class?Consts?{
????public?static?final?String?CMOWER?=?"沉默王二";
}
對(duì)于常量來(lái)說,它對(duì)于整個(gè)應(yīng)用內(nèi)的所有類都是可見的,因此是 public 的;它可以直接通過類名.常量名訪問,所以是 static 的;它是不可修改的,因此是 final 的。
另外一種常見的 final 數(shù)據(jù)就是參數(shù)了,參照程序清單 4-1。
程序清單4-1:
public?class?Cmower?{
????public?void?write(final?String?content)?{
????????//?content?+=?"猶未雪";?//?final修飾的參數(shù)是無(wú)法在方法內(nèi)部被再次修改的
????????System.out.println(content);
????}
????public?void?write1(String?content)?{
????????content?+=?"猶未雪";
????????System.out.println(content);
????}
????public?static?void?main(String[]?args)?{
????????Cmower?cmower?=?new?Cmower();
????????cmower.write("精忠報(bào)國(guó)");
????????cmower.write1("靖康恥");
????}
}
2)final 方法
在 Java 類中,所有的 private 方法都隱式地指定為 final 的(也就是說,如果你在 private 方法上加上 final 修飾符,其實(shí)是沒啥意義的)。在介紹繼承的時(shí)候,你應(yīng)該注意到我強(qiáng)調(diào)的一句話,就是新類可以直接復(fù)用基類的非 private 的屬性和方法,也就是說 private 方法是無(wú)法被繼承者修改的,因?yàn)?private 方法是 final 的。
來(lái)看程序清單 4-2,你會(huì)發(fā)現(xiàn) Wangsan 類型的 san 引用是不能調(diào)用 say(String words)
方法的,因?yàn)?private 方法是無(wú)法被繼承者修改的,盡管 Wangxiaosan 中重新定義了 say(String words)
方法。
程序清單4-2:
public?class?Wangxiaosan?extends?Wangsan?{
????public?Wangxiaosan()?{
????????say("吃中飯沒");
????}
????public?void?say(String?words)?{
????????System.out.println("王小三在說:"?+?words);
????}
????public?static?void?main(String[]?args)?{
????????Wangsan?san?=?new?Wangxiaosan();
????????//?san.say("吃晚餐沒");?//?無(wú)法訪問,并不會(huì)被覆蓋
????}
}
class?Wangsan?{
????public?Wangsan()?{
????????say("吃早飯沒");
????}
????private?void?say(String?words)?{
????????System.out.println("王三在說:"?+?words);
????}
}
3)final 類
當(dāng)我們認(rèn)為某個(gè)類就是最終的形態(tài)了,它很完美,不應(yīng)該被繼承,就可以使用final關(guān)鍵字來(lái)修飾;參照程序清單 4-3。
程序清單 4-3:
//?無(wú)法繼承
public?class?Wangxiaosan?extends?Wangsan?{
}
final?class?Wangsan?{
????public?Wangsan()?{
????????System.out.println("我就是最終形態(tài),別繼承我!");
????}
}
上一篇:Java 訪問權(quán)限控制:public、private、protected
下一篇:Java:多態(tài)乃幸福本源
微信搜索「沉默王二」公眾號(hào),關(guān)注后回復(fù)「免費(fèi)視頻」獲取 500G Java 高質(zhì)量教學(xué)視頻(已分門別類)。