六大Java功能
我花了無(wú)數(shù)小時(shí)來(lái)對(duì)不同的應(yīng)用程序進(jìn)行故障排除。 通過(guò)經(jīng)驗(yàn),我可以得出關(guān)于大多數(shù)開(kāi)發(fā)人員應(yīng)該遠(yuǎn)離的幾個(gè)Java SE功能/ API的結(jié)論。 當(dāng)我提到大多數(shù)開(kāi)發(fā)人員時(shí),我會(huì)想到常規(guī)的Java EE開(kāi)發(fā)人員,而不是庫(kù)設(shè)計(jì)人員/基礎(chǔ)結(jié)構(gòu)工程師。
全面披露:老實(shí)說(shuō),我確實(shí)認(rèn)為,大多數(shù)團(tuán)隊(duì)最好遠(yuǎn)離以下功能。 但是像往常一樣,也有例外。 如果您有強(qiáng)大的團(tuán)隊(duì)并且完全了解自己在做什么,請(qǐng)繼續(xù)。 但是,在大多數(shù)情況下,如果您開(kāi)始在軍械庫(kù)中包括以下工具,從長(zhǎng)遠(yuǎn)來(lái)看,您會(huì)后悔的:
- 反射
- 字節(jié)碼操作
- ThreadLocals
- 類(lèi)加載器
- 弱/軟引用
- 插座
但是足夠的介紹,讓我仔細(xì)閱讀警告標(biāo)志列表,并附上潛在問(wèn)題的解釋:
反思 。 在諸如Spring和Hibernate之類(lèi)的流行庫(kù)中,反射有其應(yīng)有的地位。 但是對(duì)業(yè)務(wù)代碼進(jìn)行內(nèi)省是一件很糟糕的事情,其原因有很多,我?guī)缀蹩偸墙ㄗh避免使用它:
首先是代碼可讀性/工具支持。 打開(kāi)您喜歡的IDE,并在Java代碼中找到相互依賴(lài)的關(guān)系。 很簡(jiǎn)單,不是嗎? 現(xiàn)在,將方法調(diào)用替換為反射并嘗試重復(fù)該過(guò)程。 當(dāng)您開(kāi)始修改通常應(yīng)該封裝的狀態(tài)時(shí),事情變得更加失控。 如果需要一個(gè)示例,請(qǐng)看以下代碼:
public class Secret {private String secrecy;public Secret(String secrecy) {this.secrecy = secrecy;}public String getSecrecy() {return null;} }public class TestSecrecy {public static void main(String[] args) throws Exception {Secret s = new Secret("TOP SECRET");Field f = Secret.class.getDeclaredField("secrecy");f.setAccessible(true);System.out.println(f.get(s));} }然后,您將錯(cuò)過(guò)編譯時(shí)的安全性。 看到上面的相同示例,您已經(jīng)可以看到,只有在運(yùn)行時(shí)才發(fā)現(xiàn)在getDeclaredField()參數(shù)中輸入錯(cuò)誤。 您可能還記得,發(fā)現(xiàn)運(yùn)行時(shí)錯(cuò)誤比被構(gòu)建腳本拒絕要復(fù)雜得多。
最后,會(huì)有開(kāi)銷(xiāo)。 JIT對(duì)反射調(diào)用進(jìn)行了不同的優(yōu)化。 有些優(yōu)化需要更長(zhǎng)的時(shí)間才能應(yīng)用,有些甚至無(wú)法應(yīng)用。 因此,有時(shí)對(duì)反射的性能損失可能是幾個(gè)數(shù)量級(jí)。 但是,在典型的業(yè)務(wù)應(yīng)用程序上,您不會(huì)真正注意到開(kāi)銷(xiāo),因此,這絕對(duì)可以減少麻煩。
總而言之,我可以指出,業(yè)務(wù)代碼中唯一合理的(間接)反射用法是通過(guò)AOP 。 除此之外,您最好遠(yuǎn)離反射。
字節(jié)碼操作 。 如果我看到您直接使用CGLIB或ASM您的Java EE應(yīng)用程序代碼,我感覺(jué)我立即想逃脫。 考慮我在反射塊中闡述的原因,將影響倍增五倍,您可能會(huì)開(kāi)始感到痛苦。
更糟糕的是,您在編譯期間看不到可執(zhí)行代碼。 本質(zhì)上,您不知道生產(chǎn)中實(shí)際上正在運(yùn)行什么代碼。 因此,當(dāng)遇到麻煩時(shí),您將不得不進(jìn)行運(yùn)行時(shí)故障排除和調(diào)試-如果您與我一致,這將花費(fèi)更多的時(shí)間。
ThreadLocals 。 為什么在業(yè)務(wù)代碼中看到ThreadLocals讓我感到顫抖,有兩個(gè)不相關(guān)的原因。 首先,在ThreadLocals的幫助下,您可能會(huì)開(kāi)始感到使用變量的誘惑,而無(wú)需將它們顯式傳遞給方法調(diào)用鏈。 在某些情況下可能有用。 但是當(dāng)您不小心的時(shí)候,我可以保證您最終會(huì)在代碼內(nèi)創(chuàng)建許多意外的依賴(lài)項(xiàng)。
第二個(gè)原因與我的日常工作有關(guān)。 將數(shù)據(jù)存儲(chǔ)在ThreadLocals中可以建立一條通往內(nèi)存泄漏的通道。 我所面對(duì)的10個(gè)Permgen泄漏中至少有1個(gè)是由廣泛的ThreadLocal使用引起的。 與類(lèi)加載器和線(xiàn)程池結(jié)合使用 ,很好的舊“ java.lang.OutOfMemoryError:Permgen空間”指日可待。
類(lèi)加載器 。 首先,類(lèi)加載器是一個(gè)復(fù)雜的野獸。 您必須首先了解它們,層次結(jié)構(gòu),委派機(jī)制,類(lèi)緩存等。即使您認(rèn)為已理解它們,第一次(十次)嘗試仍將無(wú)法正常進(jìn)行。 至少您最終會(huì)導(dǎo)致類(lèi)加載器泄漏。 因此,我只能建議將此任務(wù)留給應(yīng)用程序服務(wù)器。
軟參考和軟參考 。 剛剛了解了它們是什么以及它們?nèi)绾喂ぷ?#xff1f; 好。 現(xiàn)在,您對(duì)Java內(nèi)部的了解會(huì)更好一些。 有一個(gè)用軟引用重寫(xiě)所有緩存的好主意嗎? 不好。 我確實(shí)知道,配備錘子會(huì)使您四處尋找釘子。
為什么我覺(jué)得對(duì)于這種錘子而言,緩存不是一個(gè)好主意,您可能會(huì)想知道。 畢竟,在軟引用上構(gòu)建緩存可能是一個(gè)很好的示例,說(shuō)明了如何將某些復(fù)雜性委托給GC而不是自己實(shí)現(xiàn)。
讓我們以任意緩存為例。 您可以使用值的軟引用來(lái)構(gòu)建它,以便在內(nèi)存用盡時(shí)可以進(jìn)入GC并開(kāi)始清潔。 但是,現(xiàn)在您無(wú)法控制從緩存中刪除了哪些對(duì)象,并且很有可能在下次緩存未命中時(shí)重新創(chuàng)建它們。 如果內(nèi)存仍然不足,則觸發(fā)GC再次清理它們。 我想您會(huì)看到惡性循環(huán)的形成,并且您的應(yīng)用程序在Full GC不斷運(yùn)行的情況下成為CPU約束。
插座 。 普通的java.net.Socket太棘手,無(wú)法正確使用。 我確實(shí)認(rèn)為它由于具有阻塞性而從根本上存在缺陷。 當(dāng)使用基于Web的前端編寫(xiě)典型的Java EE應(yīng)用程序時(shí),您需要高度的并發(fā)性來(lái)支持眾多用戶(hù)。 您現(xiàn)在不希望發(fā)生的事情是讓您的擴(kuò)展池不那么可擴(kuò)展,等待阻塞的套接字。
不過(guò),還有許多出色的第三方庫(kù)可用于手頭的任務(wù),因此,與其嘗試自己解決問(wèn)題,不如去搶購(gòu)Netty 。
翻譯自: https://www.javacodegeeks.com/2013/09/six-java-features-to-stay-away-from.html
總結(jié)
- 上一篇: 华兴定存宝福利券怎样用?
- 下一篇: 平安富盈180收费吗?