11、乘法和除法使用移位操作
例如:
for (val = 0; val < 100000; val += 5) { a = val * 8; b = val / 2; }
用移位操作可以極大地提高性能,因爲在計算機底層,對位的操作是最方便、最快的,因此建議修改爲:
for (val = 0; val < 100000; val += 5) { a = val << 3; b = val >> 1; }
移位操作雖然快,但是可能會使代碼不太好理解,因此最好加上相應的註釋。
12、循環內不要不斷創建對象引用
例如:
for (int i = 1; i <= count; i++) { Object obj = new Object(); }
這種做法會導致內存中有count份Object對象引用存在,count很大的話,就耗費內存了,建議爲改爲:
Object obj = null; for (int i = 0; i <= count; i++) { obj = new Object(); }
這樣的話,內存中只有一份Object對象引用,每次new Object()的時候,Object對象引用指向不同的Object罷了,但是內存中只有一份,這樣就大大節省了內存空間了。
13、基於效率和類型檢查的考慮,應該儘可能使用array,無法確定數組大小時才使用ArrayList
14、儘量使用HashMap、ArrayList、StringBuilder,除非線程安全需要,否則不推薦使用Hashtable、Vector、StringBuffer,後三者由於使用同步機制而導致了性能開銷
15、不要將數組聲明爲public static final
因爲這毫無意義,這樣只是定義了引用爲static final,數組的內容還是可以隨意改變的,將數組聲明爲public更是一個安全漏洞,這意味着這個數組可以被外部類所改變
16、儘量在合適的場合使用單例
使用單例可以減輕加載的負擔、縮短加載的時間、提高加載的效率,但並不是所有地方都適用於單例,簡單來說,單例主要適用於以下三個方面:
(1)控制資源的使用,通過線程同步來控制資源的併發訪問
(2)控制實例的產生,以達到節約資源的目的
(3)控制數據的共享,在不建立直接關聯的條件下,讓多個不相關的進程或線程之間實現通信
17、儘量避免隨意使用靜態變量
要知道,當某個對象被定義爲static的變量所引用,那麼gc通常是不會回收這個對象所佔有的堆內存的,如:
public class A { private static B b = new B(); }
此時靜態變量b的生命週期與A類相同,如果A類不被卸載,那麼引用B指向的B對象會常駐內存,直到程序終止
18、及時清除不再需要的會話
爲了清除不再活動的會話,許多應用服務器都有默認的會話超時時間,一般爲30分鐘。當應用服務器需要保存更多的會話時,如果內存不足,那麼操作系統 會把部分數據轉移到磁盤,應用服務器也可能根據MRU(最近最頻繁使用)算法把部分不活躍的會話轉儲到磁盤,甚至可能拋出內存不足的異常。如果會話要被轉 儲到磁盤,那麼必須要先被序列化,在大規模集羣中,對對象進行序列化的代價是很昂貴的。因此,當會話不再需要時,應當及時調用HttpSession的 invalidate()方法清除會話。
19、實現RandomAccess接口的集合比如ArrayList,應當使用最普通的for循環而不是foreach循環來遍歷
這是JDK推薦給用戶的。JDK API對於RandomAccess接口的解釋是:實現RandomAccess接口用來表明其支持快速隨機訪問,此接口的主要目的是允許一般的算法更改 其行爲,從而將其應用到隨機或連續訪問列表時能提供良好的性能。實際經驗表明,實現RandomAccess接口的類實例,假如是隨機訪問的,使用普通 for循環效率將高於使用foreach循環;反過來,如果是順序訪問的,則使用Iterator會效率更高。可以使用類似如下的代碼作判斷:
if (list instanceof RandomAccess){ for (int i = 0; i < list.size(); i++){ } }else{ Iterator<?> iterator = list.iterable(); while (iterator.hasNext()){iterator.next() } }
foreach循環的底層實現原理就是迭代器Iterator,參見Java語法糖1:可變長度參數以及foreach循環原理。所以後半句”反過來,如果是順序訪問的,則使用Iterator會效率更高”的意思就是順序訪問的那些類實例,使用foreach循環去遍歷。
20、使用同步代碼塊替代同步方法
這點在多線程模塊中的synchronized鎖方法塊一文中已經講得很清楚了,除非能確定一整個方法都是需要進行同步的,否則儘量使用同步代碼塊,避免對那些不需要進行同步的代碼也進行了同步,影響了代碼執行效率。