java可以返回微妙吗_Java开发中10个最为微妙的最佳编程实践
這是10個(gè)最佳實(shí)踐的列表,比你平時(shí)在Josh Bloch的《effective java》中看到的規(guī)則更加精妙。和Josh Bloch列出的非常容易學(xué)習(xí)的、和日常情況息息相關(guān)的實(shí)踐相比,這個(gè)列表中提到了一些關(guān)于設(shè)計(jì)API/SPI的實(shí)踐,雖然不常見,但是存在很大的效率問題。
我在編寫和維護(hù)jOOQ(一種內(nèi)部DSL,在java中將SQL模塊化)時(shí),碰到了這些問題。作為內(nèi)部DSL,jOOQ最大限度的挑戰(zhàn)了java編譯器和泛型,把泛型,變量和重載結(jié)合到了一起。這種太寬泛的API是Josh Bloch相當(dāng)不推薦的。
讓我來和你分享這10個(gè)java編碼中微妙的最佳實(shí)踐:
1.牢記C++的析構(gòu)函數(shù)
還記得C++中的析構(gòu)函數(shù)嗎?不記得了?或許你真的很幸運(yùn),因?yàn)槟阍僖膊槐貫閯h除對象后,沒有及時(shí)釋放內(nèi)存而造成內(nèi)存泄露進(jìn)行調(diào)試了。我們真的應(yīng)該感謝Sun和Oracle實(shí)現(xiàn)垃圾回收機(jī)制。
盡管如此,對于我們來說,析構(gòu)函數(shù)仍然有一個(gè)很有趣的特點(diǎn)。它常常會(huì)讓我們對以和分配內(nèi)存相反的順序釋放內(nèi)存的工作模式感到容易理解。同樣,在JAVA代碼中,當(dāng)你處理如下類析構(gòu)函數(shù)語法的時(shí)候,也要把這個(gè)特性牢記在心:
? 當(dāng)使用@Before和@After但與注解時(shí);
? 當(dāng)分配和釋放JDBC資源時(shí);
? 當(dāng)調(diào)用父類的方法時(shí)。
也有其他不同的使用案例。這有一個(gè)顯示如何實(shí)現(xiàn)事件監(jiān)聽的實(shí)例:
@Overridepublicvoid beforeEvent(EventContext e) {
super.beforeEvent(e);//Super code before my code
}
@Overridepublicvoid afterEvent(EventContext e) {//Super code after my code
super.afterEvent(e);
}
法則:無論何時(shí),當(dāng)你使用before/after, allocate/free, take/return語法實(shí)現(xiàn)邏輯時(shí),仔細(xì)想想是否需要反序的使用after/free/return操作。
2. 不要相信你早期的SPI演進(jìn)判斷
為使用者提供SPI可以很容易讓他們注入自定義行為到你的庫/代碼。當(dāng)心你的SPI演進(jìn)判斷可能會(huì)迷惑你,讓你認(rèn)為(不)需要附加的參數(shù)。當(dāng)然,不應(yīng)該過早的添加功能。但是一旦你發(fā)布了SPI,一旦你決定遵循語義版本,當(dāng)你發(fā)現(xiàn)你可能在某些情況下需要另外一個(gè)參數(shù)時(shí),你將真的后悔為SPI添加了一個(gè)愚蠢的單參數(shù)方法:
interface EventListener {//Bad
void message(Stringmessage);
}
如果你也需要消息ID和消息源,怎么辦?對于上面的類型,API演進(jìn)將會(huì)阻礙你添加參數(shù)。當(dāng)然,有了Java8,你可以添加一個(gè)defender方法,“防御”你早期糟糕的設(shè)計(jì)決策:
interface EventListener {//Bad
default void message(Stringmessage) {
message(message,null,null);
}//Better?
void message(Stringmessage,Integerid,
MessageSource source
);
}
注意很不幸defender方法不能為final。
但是比起用數(shù)十個(gè)方法污染你的SPI,使用一個(gè)上下文對象(或參數(shù)對象)好很多。
interface MessageContext {Stringmessage();Integerid();
MessageSource source();
}
interface EventListener {//Awesome!
void message(MessageContext context);
}
比起EventListner SPI你可以更容易演進(jìn)MessageContext API,因?yàn)楹苌儆脩魰?huì)實(shí)現(xiàn)它。
規(guī)則: 無論何時(shí)你指定SPI的時(shí)候, 考慮使用上下文/參數(shù)對象,而不要編寫固定參數(shù)數(shù)量的方法。
備注: 使用特定的MessageResult類型傳遞結(jié)果也是一個(gè)好的想法,該類型可以通過構(gòu)造器API構(gòu)建。這將會(huì)為你的SPI提供更多的SPI演進(jìn)靈活性。
3.避免使用匿名,局部或內(nèi)部類
Swing程序員通常只要按幾下快捷鍵即可生成成百上千的匿名類。在多數(shù)情況下,只要遵循接口、不違法SPI子類型的生命周期(SPI subtype lifecycle),這樣做也無妨。
但是不要因?yàn)橐粋€(gè)簡單的原因——它們會(huì)保存對外部類的引用,就頻繁的使用匿名、局部或者內(nèi)部類。因?yàn)闊o論它們走到哪,外部類就得跟到哪。例如,在局部類的域外操作不當(dāng)?shù)脑?#xff0c;那么整個(gè)對象圖就會(huì)發(fā)生微妙的變化從而可能引起內(nèi)存泄露。
規(guī)則:在編寫匿名、局部或內(nèi)部類前請三思能否將它轉(zhuǎn)化為靜態(tài)的或普通的頂級類,從而避免方法將它們的對象返回到更外層的域中。
注意:使用雙層花括號來初始化簡單對象:
newHashMap() {{
put("1","a");
put("2","b");
}}
這個(gè)方法利用了 JLS §8.6規(guī)范里描述的實(shí)例初始化方法(initializer)。表面上看起來不錯(cuò),但實(shí)際上不提倡這種做法。因?yàn)橐鞘褂猛耆?dú)立的HashMap對象,那么實(shí)例就不會(huì)一直保存著外部對象的引用。此外,這也會(huì)讓類加載器管理更多的類。
總結(jié)
以上是生活随笔為你收集整理的java可以返回微妙吗_Java开发中10个最为微妙的最佳编程实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c++ udp通信_Web 通信协议,你
- 下一篇: python爬虫之逆向破解_Python