本文的主要類容來自 微信公衆號 : java後端技術, (以後瞭解到的其餘細節也會在此文中進行補充)java
1、 代碼優化的目的:數據庫
1,減少代碼體積 : 還有助於增長代碼的可閱讀性(這個很重要)編程
2,提升運算效率後端
2、 代碼優化細節api
一、儘可能指定類、 變量、 方法的 final 修飾符數組
帶有修飾符的類是不可派生的, 在java的api中 像String之類的就是屬於這類。安全
被final修飾的類不能被繼承, 被final修飾的方法不能被重寫。 若是指定一個類是final的,那麼這個類中全部的方法都是final的。微信
文中的做者指出: java的編譯器會內聯全部的final方法, 這對java運行效率提高很大, (能夠達到 50% 左右)。session
二、儘可能重用對象, 特別是String對象的使用, 出現字符串鏈接的時候, 應該使用StringBuilder 或者 StringBuffer代替, 由於java數據結構
虛擬機 不只要建立String對象(String對象爲final對象,不能被改變), 這樣能夠減小內存中的對象信息,。
3,、若是能夠的話, 儘可能使用局部變量, 局部變量 存在與 stack中, 隨着方法運行的結束 而消失。 而其餘的變量 則會存在與heap中, 這在
方法運行結束後 還須要額外的垃圾回收。
四、及時的關閉流, 在進行數據庫鏈接或者 io編程的時候, 在使用完畢應立即使的關閉 用來釋放資源。 由於流的操做會形成極大的性能開銷。
五、儘量的減小重複的計算 , 在方法的調用的時候, 即使只有一句話,也是系統的性能開銷。 在進行 集合 或者數組的遍歷的時候, 其長度
能夠先計算出來。尤爲是在 length恆大的時候, 對性能的提升就愈加的明顯
六、儘可能使用 懶加載策略, 在已經立刻須要該類的時候再去創造該類。
七、謹慎使用 異常, 在使用異常的時候 java虛擬機 就必定回去調用堆棧信息, 消耗不少資源。 因此不要爲了達到某個普通的邏輯功能來使用異常。
八、try catch 語句 最好放在最外面, 不要被選擇 ,循環等判斷。
九、若是能估計到 最後添加的類容的長度, 能夠爲 底層使用數組方法、實現的集合指定長度 : ArryList 、 LinkeList 、 StringBuffer 、 StringBuidler
HashMap 、 HashSet 等。 由於 當集合數據滿時, 會自動在底層建立一個 兩倍當前長度的 集合,並將數據拷貝到新集合中。 而集合的初始
默認長度較小, 因此數據量較大的時候, 會建立不少 類, 消耗大量的資源。
十、當複製大量數據的時候, 使用 System.arrycopy()
十一、 乘法 和 除法使用移位操做, 這回加快計算機的執行速度
十二、循環內不要建立新的對象引用, 由於 若是循環量較大的話, 會在 stack中建立大量的臨時引用。
1三、如無必要, 應當儘可能使用 array , 而不是使用 arrayList(當沒法肯定數組大小的時候再使用 list)
1四、若是沒有同步要求, 儘可能使用 HashMap, ArrayList, StringBuilder。 不要使用 Hashtable, Vechtor,StringBuffer
1五、不要將一個數組 聲明成一個 public static final 數組聲明爲 final 也仍是能被改變, 而一個public 的數組明顯並不安全。
1六、 在合適的場合使用單例模式 : 單例模式 能夠減輕加載的負擔, 減小加載的時間, 提升加載的效率,
使用場合 : 1)控制資源使用, 經過線程同步來控制資源的併發訪問
2)控制數據的共享, 以達到節約資源的目的
3)控制數據共享, 再不創建直接關聯的狀況下, 讓多個不相干的進程和線程中實現共享。
1七、儘可能避免隨意使用靜態變量, 一個靜態的變量 通常不會被 gc 回收,。
1八、及時清除不須要的會話 session 等 。
1九、 實現 RandomAccess 接口的集合 (ArryList 等) , 應當使用普通的 for 循環 而不是 forEach循環。
由於foreach 循環底層使用的是 iterator , 其是順序訪問的, 而RandomAccess接口代表支持隨記訪問。
而隨記訪問使用 for 循環更加的高效 , 反之亦然。
20、使用同步代碼塊 來代替 同步方法,
2一、將常量聲明爲 static final ,並大寫命名 : 虛擬機會將該常量放入常量池。
2二、不要建立一些不使用的 對象, 不要引入一些不使用的類。
2三、 少使用 反射, 雖然反射機制很是強大, 可是效率不過高。 建議: 在項目啓動的時候 經過反射機制將要反射的地方建立出反射的對象。
2四、使用數據庫鏈接池 和 線程池 (不用解釋)
2五、使用帶緩衝的輸入輸出流
2六、順序插入和隨機訪問較多的地方 使用 ArrayList , 刪除和中間插入比較多的使用 LinkedList (底層數據結構)。
2七、public 方法中不要有太多形參
2八、字符串變量 和 字符串常量進行比較的時候將 常量放在前面。
2九、在java中 i==1 和 1==i是沒有什麼區別的, 可是在習慣上使用 i == 1.
30、不建議對 數組使用 toString 方法, 由於 會打印成一個 哈希地址, 可是能夠對 集合使用toString方法, 由於其父類中重寫了 toSting方法。
3一、不要對超出範圍的基本數據類型使用強制向下轉型。如: 將一個 long 類型的強制轉換成一個 int類型的, 這是由於 : 在java中向下轉型是
切斷了long 的高 32 爲二進制碼, 因此並不能直接獲得 是、十進制上的後面位數。
3二、在公共的集合中, 不使用的類要即便清理掉, 集合沒有在方法中的話, 只要對象一直存在集合就會一直存在, 隨着使用的增長, 集合中的數據也會增長
當增長到必定程度時 , 有可能形成內存泄露隱患。
3三、若是將一個 基本數據類型轉換成一個字符串, 那麼 運行速度最快的是 toString()方法, 以後是 String.valueOf(), 在以後是 「」 + 「」 最慢
由於String.valueOf()底層使用的是toString方法, 而 「」+底層使用的是 Stringuilder實現的。
3四、使用最有效率的方法來遍歷 Map
public static void main(String [] args){ HashMap<String, String> hm = new HashMap<String, String>; hm.put("hehe","java"); Set<Map.entry<String,String>> entrySet = hm.entrySet(); Iterator it = entrySet.iterator(); while(it.hasNext()){ ...... } }
若是隻想遍歷 key的話, 使用 keySet就行了
3五、對資源的 close 應當分開進行: 由於一個 close 操做的時要 使用try catch 語句進行異常處理, 若是有多個close, 當一個出現了異常
那麼他後面的 close就能操做了。
3六、在使用 ThreadLocal 的時候, 在使用前 和使用後都要進行 remove 操做。
由於在使用 線程池的時候, 當一個線程使用結束以後, 會將其放入線程池中,而不會將其 銷燬, 咱們拿到一個線程以後, 極可能
拿到其上綁定的其它數據, 由此形成的異常很是難以查明。
3七、應當使用 常量的定義來代替魔鬼數字(沒有具體含義的數字 和 字符串), 會極大地提升可閱讀性。
3八、在long 或者 Long 類型賦值的時候 應當使用 L 而不是 l, 由於 l 易於 1 混淆。
3九、全部重寫的方法都應當 保留 @Override 註解
一是這樣能夠 知道這個放法是個重寫方法,
二是可以判斷你的重寫是否有語法錯誤
三是在抽像類 或者 接口中進行 簽名修改的時候, 繼承類中會出現異常, 容易定義到具體的類。
40、在循環 中 不要使用 + 進行字符串的拼接, 直接使用 StringBuilder 的 apperd方法進行拼接。
前面提到過 + 操做底層使用的是 SringBuilder 進行的, 這樣就會生成 循環次數 個 StringBuilder
4一、推薦使用 jdk7 中提供的 行的 Objects 類進行equals比較, 直接使用 equals 有空指針危險。
4二、不要使用多線程對 一個 Random對象進行操做, 雖然沒有線程安全問題, 可是會下降性能,推薦使用 ThreadLocalRandom
4三、 靜態類 、單例類 、 工廠類 的構造器使用 private