「通用篇」討論的問題適合於大多數Java應用。java
1.1 不用new關鍵詞建立類的實例設計模式
用new關鍵詞建立類的實例時,構造函數鏈中的全部構造函數都會被自動調用。但若是一個對象實現了Cloneable接口,咱們能夠調用它的clone()方法。clone()方法不會調用任何類構造函數。數組
在使用設計模式(Design Pattern)的場合,若是用Factory模式建立對象,則改用clone()方法建立新的對象實例很是簡單。例如,下面是Factory模式的一個典型實現:服務器
public static Credit getNewCredit()
{併發
return new Credit();ide
}函數
改進後的代碼使用clone()方法,以下所示:性能
private static Credit BaseCredit = new Credit();
public static Credit getNewCredit()優化
{spa
return (Credit) BaseCredit.clone();
}
上面的思路對於數組處理一樣頗有用。
1.2 使用非阻塞I/O
版本較低的JDK不支持非阻塞I/O API。爲避免I/O阻塞,一些應用採用了建立大量線程的辦法(在較好的狀況下,會使用一個緩衝池)。這種技術能夠在許多必須支持併發I/O流的應用中見到,如Web服務器、報價和拍賣應用等。然而,建立Java線程須要至關可觀的開銷。
JDK 1.4引入了非阻塞的I/O庫(java.nio)。若是應用要求使用版本較早的JDK,在這裏有一個支持非阻塞I/O的軟件包。
1.3 慎用異常
異常對性能不利。拋出異常首先要建立一個新的對象。Throwable接口的構造函數調用名爲fillInStackTrace()的本地 (Native)方法,fillInStackTrace()方法檢查堆棧,收集調用跟蹤信息。只要有異常被拋出,VM就必須調整調用堆棧,由於在處理過程當中建立了一個新的對象。
異常只能用於錯誤處理,不該該用來控制程序流程。
1.4 不要重複初始化變量
默認狀況下,調用類的構造函數時, Java會把變量初始化成肯定的值:全部的對象被設置成null,整數變量(byte、short、int、long)設置成0,float和 double變量設置成0.0,邏輯值設置成false。當一個類從另外一個類派生時,這一點尤爲應該注意,由於用new關鍵詞建立一個對象時,構造函數鏈中的全部構造函數都會被自動調用。
1.5 儘可能指定類的final修飾符
帶有final修飾符的類是不可派生的。在Java核心API中,有許多應用final的例子,例如java.lang.String。爲String類指定final防止了人們覆蓋length()方法。
另外,若是指定一個類爲final,則該類全部的方法都是final。Java編譯器會尋找機會內聯(inline)全部的final方法(這和具體的編譯器實現有關)。此舉可以使性能平均提升50%。
1.6 儘可能使用局部變量
調用方法時傳遞的參數以及在調用中建立的臨時變量都保存在棧(Stack)中,速度較快。其餘變量,如靜態變量、實例變量等,都在堆(Heap)中建立,速度較慢。另外,依賴於具體的編譯器/JVM,局部變量還可能獲得進一步優化。請參見《儘量使用堆棧變量》。
1.7 乘法和除法
考慮下面的代碼:
for (val = 0; val < 100000; val +=5)
{
alterX = val * 8;
myResult = val * 2;
}
用移位操做替代乘法操做能夠極大地提升性能。下面是修改後的代碼:
for (val = 0; val < 100000; val += 5)
{
alterX = val << 3;
myResult = val << 1;
}
修改後的代碼再也不作乘以8的操做,而是改用等價的左移3位操做,每左移1位至關於乘以2。相應地,右移1位操做至關於除以2。值得一提的是,雖然移位操做速度快,但可能使代碼比較難於理解,因此最好加上一些註釋。