Java編程性能優化一些事兒

在JAVA程序中,性能問題的大部分緣由並不在於JAVA語言,而是程序自己。養成良好的編碼習慣很是重要,可以顯著地提高程序性能。
1.儘可能使用final修飾符
帶有final修飾符的類是不可派生的。在JAVA核心API中,有許多應用final的例子,例如java.lang.String,爲String類指定final防止了使用者覆蓋length()方法。另外,若是一個類是final的,則該類全部方法都是final的。java編譯器會尋找機會內聯(inline)全部的final方法(這和具體的編譯器實現有關)。此舉可以使性能平均提升50%。
2.儘可能重用對象
特別是String對象的使用中,出現字符串鏈接狀況時應使用StringBuffer代替,因爲系統不只要花時間生成對象,之後可能還須要花時間對這些對象進行垃圾回收和處理。所以生成過多的對象將會給程序的性能帶來很大的影響。
3.儘可能使用局部變量
調用方法時傳遞的參數以及在調用中建立的臨時變量都保存在棧(Stack)中,速度較快。其餘變量,如靜態變量,實例變量等,都在堆(Heap)中建立,速度較慢。
4.不要重複初始化變量
默認狀況下,調用類的構造函數時,java會把變量初始化成肯定的值,全部的對象被設置成null,整數變量設置成0,float和double變量設置成0.0,邏輯值設置成false。當一個類從另外一個類派生時,這一點尤爲應該注意,由於用new關鍵字建立一個對象時,構造函數鏈中的全部構造函數都會被自動調用。
這裏有個注意,給成員變量設置初始值但須要調用其餘方法的時候,最好放在一個方法好比initXXX()中,由於直接調用某方法賦值可能會由於類還沒有初始化而拋空指針異常,如:public int state = this.getState();
5.在java+Oracle的應用系統開發中,java中內嵌的SQL語言應儘可能使用大寫形式,以減小Oracle解析器的解析負擔。
6.在java編程過程當中,進行數據庫鏈接,I/O流操做,在使用完畢後,及時關閉以釋放資源。由於對這些大對象的操做會形成系統大的開銷。
7.過度的建立對象會消耗系統的大量內存,嚴重時,會致使內存泄漏,所以,保證過時的對象的及時回收具備重要意義。JVM的GC並不是十分智能,所以建議在對象使用完畢後,手動設置成null。
8.在使用同步機制時,應儘可能使用方法同步代替代碼塊同步
9.儘可能減小對變量的重複計算
好比for(int i=0;i<list.size();i++) 應修改成for(int i=0,len=list.size();i&lt;len;i++)
10.採用在須要的時候纔開始建立的策略
例如:String str="abc";
if(i==1){ list.add(str);}
應修改成:
if(i==1){String str="abc"; list.add(str);}
11.慎用異常,異常對性能不利
拋出異常首先要建立一個新的對象。Throwable接口的構造函數調用名爲fillInStackTrace()的本地方法,fillInStackTrace()方法檢查棧,收集調用跟蹤信息。只要有異常被拋出,VM就必須調整調用棧,由於在處理過程當中建立了一個新的對象。
異常只能用於錯誤處理,不該該用來控制程序流程。
12.不要在循環中使用Try/Catch語句,應把Try/Catch放在循環最外層
Error是獲取系統錯誤的類,或者說是虛擬機錯誤的類。不是全部的錯誤Exception都能獲取到的,虛擬機報錯Exception就獲取不到,必須用Error獲取。
13.經過StringBuffer的構造函數來設定他的初始化容量,能夠明顯提高性能
StringBuffer的默認容量爲16,當StringBuffer的容量達到最大容量時,她會將自身容量增長到當前的2倍+2,也就是2*n+2。不管什麼時候,只要StringBuffer到達她的最大容量,她就不得不建立一個新的對象數組,而後複製舊的對象數組,這會浪費不少時間。因此給StringBuffer設置一個合理的初始化容量值,是頗有必要的!
14.合理使用java.util.Vector
Vector與StringBuffer相似,每次擴展容量時,全部現有元素都要賦值到新的存儲空間中。Vector的默認存儲能力爲10個元素,擴容加倍。
vector.add(index,obj) 這個方法能夠將元素obj插入到index位置,但index以及以後的元素依次都要向下移動一個位置(將其索引加 1)。 除非必要,不然對性能不利。
一樣規則適用於remove(int index)方法,移除此向量中指定位置的元素。將全部後續元素左移(將其索引減 1)。返回此向量中移除的元素。因此刪除vector最後一個元素要比刪除第1個元素開銷低不少。刪除全部元素最好用removeAllElements()方法。
若是要刪除vector裏的一個元素可使用 vector.remove(obj);而沒必要本身檢索元素位置,再刪除,如int index = indexOf(obj);vector.remove(index);
15.當複製大量數據時,使用System.arraycopy();
16.代碼重構,增長代碼的可讀性
17.不用new關鍵字建立對象的實例
用new關鍵詞建立類的實例時,構造函數鏈中的全部構造函數都會被自動調用。但若是一個對象實現了Cloneable接口,咱們能夠調用她的clone()方法。clone()方法不會調用任何類構造函數。
下面是Factory模式的一個典型實現。
public static Credit getNewCredit()
{
    return new Credit();
}
改進後的代碼使用clone()方法,
private static Credit BaseCredit = new Credit();
public static Credit getNewCredit()
{
    return (Credit)BaseCredit.clone();
}
18.乘除法若是可使用位移,應儘可能使用位移,但最好加上註釋,由於位移操做不直觀,難於理解。
19.不要將數組聲明爲:public static final
20.HaspMap的遍歷。
Map&lt;String, String[]> paraMap = new HashMap<String, String[]>();
for( Entry<String, String[]> entry : paraMap.entrySet() )
{
    String appFieldDefId = entry.getKey();
    String[] values = entry.getValue();
}
利用散列值取出相應的Entry作比較獲得結果,取得entry的值以後直接取key和value。
21.array(數組)和ArrayList的使用。
array 數組效率最高,但容量固定,沒法動態改變,ArrayList容量能夠動態增加,但犧牲了效率。
22.單線程應儘可能使用 HashMap, ArrayList,除非必要,不然不推薦使用HashTable,Vector,她們使用了同步機制,而下降了性能。
23.StringBuffer,StringBuilder的區別在於:java.lang.StringBuffer 線程安全的可變字符序列。一個相似於String的字符串緩衝區,但不能修改。StringBuilder與該類相比,一般應該優先使用StringBuilder類,由於她支持全部相同的操做,但因爲她不執行同步,因此速度更快。爲了得到更好的性能,在構造StringBuffer或StringBuilder時應儘可能指定她的容量。固然若是不超過16個字符時就不用了。
相同狀況下,使用StringBuilder比使用StringBuffer僅能得到10%~15%的性能提高,但卻要冒多線程不安全的風險。綜合考慮仍是建議使用StringBuffer。
24.儘可能使用基本數據類型代替對象。
25.用簡單的數值計算代替複雜的函數計算,好比查表方式解決三角函數問題。
26.使用具體類比使用接口效率高,但結構彈性下降了,但現代IDE均可以解決這個問題。
27.考慮使用靜態方法,若是你沒有必要去訪問對象的外部,那麼就使你的方法成爲靜態方法。她會被更快地調用,由於她不須要一個虛擬函數導向表。這同事也是一個很好的實踐,由於她告訴你如何區分方法的性質,調用這個方法不會改變對象的狀態。
28.應儘量避免使用內在的GET,SET方法。
android編程中,虛方法的調用會產生不少代價,比實例屬性查詢的代價還要多。咱們應該在外部調用的時候才使用get,set方法,但在內部調用的時候,應該直接調用。
29.避免枚舉,浮點數的使用。
30.二維數組比一維數組佔用更多的內存空間,大概是10倍計算。java

以上僅是Java方面編程時的性能優化,性能優化大部分都是在時間、效率、代碼結構層次等方面的權衡,各有利弊,不要把上面內容當成教條,或許有些對咱們實際工做適用,有些不適用,還望根據實際工做場景進行取捨吧,活學活用,變通爲宜。android

相關文章
相關標籤/搜索