開發者應該避免使用的6個Java功能

jopen 11年前發布 | 27K 次閱讀 Java Java開發

摘要:作者從多年的經驗中吸取到,有六個Java SE功能/API是不提倡Java程序員使用的,它們分別是Reflection、Bytecode manipulation、ThreadLocals、Classloaders、Weak/Soft references、Sockets。

本文作者是一名擁有多年Java開發經驗的程序員,他從經驗中得出,并不是所有的Java SE功能/API都值得程序員去使用,比如本文列舉的這6個,大家在使用前得慎重對待。以下是對原文的摘譯。

多年的Java開發經驗告訴我,從長遠角度來看,以下這些Java SE功能/API,開發者最好停止使用。 

  • Reflection
  • Bytecode manipulation 
  • ThreadLocals
  • Classloaders
  • Weak/Soft references
  • Sockets 

1.Reflection

Reflection即反射,在許多流行的庫里面都有反射機制,比如Spring和Hibernate。通過對業務代碼進行反思,我建議大家避免使用反射。下面列出我反對使用的原因:

首先涉及到代碼可讀性/工具支持。打開IDE并且在Java代碼里找到相互依賴關系。使用relection替換方法調用,并且試著重復該步驟。事情變的愈發不可收拾,正常情況下都應該封裝好了再修改狀態。下面來看看具體代碼示例:

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));
    }
}
通過查看以上代碼可以得知,方法getDeclaredField()參數只有在運行時才可以被發現。而你也清楚,運行時產生的bug總比不執行腳本要更加棘手。

其次,反射調用優化是由JIT執行的,一些優化可能需要花費很長時間才能得到應用,而有些優化甚至都得不到應用,所以關于反射的性能優化有時會被數量化。但在一個典型的業務應用程序中——你可能不會真正意識到這些性能開銷。

總之,開發者應該通過AOP合理地在業務層使用反射,除此以外,你最好離它遠遠的。

2.Bytecode manipulation.

字節碼操作,如果我看到你在Java EE應用程序里直接使用CGLIBASM,我可能會立即跑開。

最糟糕的事情莫過于在編譯期間沒有任何可執行的代碼。實際上,當產品在運行時,你根本不知道哪塊代碼在運行。所以,當你遇到麻煩時,會自然地把錯誤拋給運行時故障排除和調試,不過這樣反而會更麻煩。

3.ThreadLocals

這里有兩個不相關的原因,當我在業務層代碼里看到ThreadLocals時會顫抖。首先,在ThreadLocals的幫助里,你可能會看到許多變量的使用都沒有通過方法調用鏈來明確地向下傳遞。這在某些場合下是有用的,但當你一旦粗心,你會在代碼里構建許多意料不到的依賴關系。

第二個不相關的原因與我日常的工作相關,在ThreadLocals里存儲數據會引發內存泄露。最起碼我遇到的Permgen泄露有十分之一都是使用 ThreadLocals造成的,在結合了類加載器和線程池后,“java.lang.OutOfMemoryError:Permgen space”異常可能就馬上出現了。

4.Classloaders

首先,類加載器是一個復雜的野獸。你必須先了解它的層次結構、委托機制、類緩存等等。即使你認為自己已經掌握了,它可能還是不能正常工作。最終將導致一個類加載器泄露問題。因此我只能建議你將這個任務留給應用服務器處理

5.Weak/Soft references

現在,你應該更好的理解Java的內部方法。使用軟引用來重寫所有的緩存并不明智。我知道,當你手上拿著錘子的時候,就會到處尋找釘子。可對于錘子來說,緩存并不是個好釘子。為什么?基于軟引用構建緩存可能是如何委托一些復雜因素到GC而不是通過自身實現的一個好例子。

下面舉個緩存的例子,你使用軟引用來創建數據,當內存被耗盡時,GC進入并且進行清理。但是,緩存中被刪除的對象并未得到你的控制,而且很有可能在下一次的 cache-miss中重新創建。如果內存仍然不足,你可以觸發GC進行再次清理。你可能已經看出了整個運行過程的惡性循環,整個應用程序就變成了CPU 與GC不斷運行的狀態了

6.Sockets 

普通老式的java.net.Socket實在是太復雜,以至于很難弄正確。我覺得阻塞性是其根本性的缺陷。當你編寫一個典型的帶有Web前端的Java EE應用程序時,應用程序需要高并發度來支持大量的用戶,而你現在最不想發生的是不具有可擴展的線程池坐等阻塞套接字。

目前有許多精彩可用的第三方庫,使用它們可以更好的完成任務,比如Netty,開發者不妨嘗試下。(編譯:張紅月 審核:王果)

來自:Plumbr

來自:http://www.csdn.net/article/2013-10-21/2817231-Six-Java-features-to-stay-away-from

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!