android之java程序性能優化

在JAVA程序中,性能問題的大部分原因並不在於JAVA語言,而是程序本身。養成良好的編碼習慣非常重要,能夠顯著地提升程序性能。

一、避免在循環條件中使用複雜表達式 

在不做編譯優化的情況下,在循環中,循環條件會被反覆計算,如果不使用複雜表達式,而使循環條件值不變的話,程序將會運行的更快。還有一個原則,決不在一個For語句中第二次調用一個類的方法 

例子:

[java] view plaincopy
  1. class cel {  
  2.     void method (vector vector) {  
  3.         for (int i = 0; i < vector.size (); i++)  // violation  
  4.             ; // ...  
  5.     }  
優化:
[java] view plaincopy
  1. void method (vector vector) {  
  2.        int size = vector.size ();  
  3.        for (int i = 0; i < size; i++)  
  4.            ; // ...  
  5.    }  

或者

[java] view plaincopy
  1. void method (vector vector) {  
  2.        for (int i = 0,size = vector.size ();i < size; i++)  
  3.            ; // ...  
  4.    }  

二、讓訪問實例內變量的getter/setter方法變成”final” 

例子:

[java] view plaincopy
  1. public void setsize (int size) {  
  2.         _size = size;  
  3.    }  

優化:

[java] view plaincopy
  1. final public void setsize (int size) {  
  2.          _size = size;  
  3.     }  

三、在字符串相加的時候,使用 ' ' 代替 " ",如果該字符串只有一個字符的話
例子:

[java] view plaincopy
  1. public void method(string s) {  
  2.         string string = s + "d"  // violation.  
  3.         string = "abc" + "d"      // violation.  
  4.     }  

優化:

[java] view plaincopy
  1. public void method(string s) {  
  2.        string string = s + 'd'  
  3.        string = "abc" + 'd'     
  4.    }  

四、將try/catch塊移出循環
把try/catch塊放入循環體內,會極大的影響性能,如果編譯jit被關閉或者你所使用的是一個不帶jit的jvm,性能會將下降21%之多
例子:

[java] view plaincopy
  1. void method (fileinputstream fis) {  
  2.         for (int i = 0; i < size; i++) {  
  3.             try {                                      // violation  
  4.                 _sum += fis.read();  
  5.             } catch (exception e) {}  
  6.         }  
  7.     }  

優化;

[java] view plaincopy
  1. void method (fileinputstream fis) {  
  2.         try {  
  3.             for (int i = 0; i < size; i++) {  
  4.                 _sum += fis.read();  
  5.             }  
  6.         } catch (exception e) {}  
  7.     }  

五、對於boolean值,避免不必要的等式判斷 
將一個boolean值與一個true比較是一個恆等操作(直接返回該boolean變量的值). 移走對於boolean的不必要操作至少會帶來2個好處: 
1)代碼執行的更快 (生成的字節碼少了5個字節); 
2)代碼也會更加乾淨

例子:

[java] view plaincopy
  1. boolean method (string string) {  
  2.        return string.endswith ("a") == true;   // violation  
  3.    }  

優化:

[java] view plaincopy
  1. boolean method (string string) {  
  2.        return string.endswith ("a");  
  3.    }  

六、使用條件操作符替代"if (cond) return; else return;" 結構

例子:

[java] view plaincopy
  1. public int method(boolean isdone) {  
  2.        if (isdone) {  
  3.            return 0;  
  4.        } else {  
  5.            return 10;  
  6.        }  
  7.    }  

優化:

[java] view plaincopy
  1. public int method(boolean isdone) {  
  2.         return (isdone ? 0 : 10);  
  3.     }  

七、使用條件操作符代替"if (cond) a = b; else a = c;" 結構
例子:

[java] view plaincopy
  1. void method(boolean istrue) {  
  2.         if (istrue) {  
  3.             value = 0;  
  4.         } else {  
  5.             value = 1;  
  6.         }  
  7.     }  

優化:

[java] view plaincopy
  1. void method(boolean istrue) {  
  2.         _value = (istrue ? 0 : 1);       // compact expression.  
  3.     }  

八、不要在循環體中實例化變量
在循環體中實例化臨時變量將會增加內存消耗
例子:

[java] view plaincopy
  1. void method (vector v) {  
  2.         int size = v.size();  
  3.         for (int i=0;i < size;i++) {  
  4.             object o = new object();  
  5.             o = v.elementat(i);  
  6.         }  
  7.     }  

優化:

在循環體外定義變量,並反覆使用

[java] view plaincopy
  1. void method (vector v) {  
  2.         int size = v.size();  
  3.         object o;  
  4.         for (int i=0;i<size;i++) {  
  5.             o = v.elementat(i);  
  6.         }  
  7.     }  

九、儘量使用final修飾符

帶有final修飾符的類是不可派生的。在JAVA核心API中,有許多應用final的例子,例如 java.lang.String。

爲String類指定final防止了使用者覆蓋length()方法。另外,如果一個類是final的,則該類所有方法都是final的。java編譯器會尋找機會內聯(inline)所有的final方法(這和具體的編譯器實現有關)。此舉能夠使性能平均提高 50%。

十、儘量重用對象

特別是String對象的使用中,出現字符串連接情況時應使用StringBuffer代替,由於系統不僅要花時間生成對象,以後可能還需要花時間對這些對象進行垃圾回收和處理。因此生成過多的對象將會給程序的性能帶來很大的影響。 

十一、儘量使用局部變量

調用方法時傳遞的參數以及在調用中創建的臨時變量都保存在棧(Stack)中,速度較快。其他變量,如靜態變量(static),實例變量等,都在堆(Heap)中創建,速度較慢。尤其是static,儘量少用,如果程序中存在大量static,說明程序的設計有問題.(很可能會佔用大量內存)

十二、不要重複初始化變量

默認情況下,調用類的構造函數時,java會把變量初始化成確定的值,所有的對象被設置成null,整數變量設置成0,float和double變量設置成0.0,邏輯值設置成false。當一個類從另一個類派生時,這一點尤其應該注意,因爲用new關鍵字創建一個對象時,構造函數鏈中的所有構造函數都會被自動調用。

例如:

[java] view plaincopy
  1. class test{  
  2. private Object obj; //不需要寫成 private Object obj=null;  
  3. }  

初始化就是賦值,賦值就是初始化
這裏有個注意,給成員變量設置初始值但需要調用其他方法的時候,最好放在一個方法比如initXXX()中,因爲直接調用某方法賦值可能會因爲類尚未初始化而拋空指針異常,public int state = this.getState();

十三、保證對象能夠被及時回收

過分的創建對象會消耗系統的大量內存,嚴重時,會導致內存泄漏,因此,保證過期的對象的及時回收具有重要意義。 JVM的GC並非十分智能,因此建議在對象使用完畢後,手動設置成null。

十四、採用在需要的時候纔開始創建的策略

例如:

[java] view plaincopy
  1. String str="abc";     
  2. if(i==1){  
  3.  list.add(str);  
  4. }    

優化:

[java] view plaincopy
  1. if(i==1){  
  2.  String str="abc";  
  3.  list.add(str);  
  4. }    

十五、不要將數組聲明爲:public static final

 

十六、array(數組)和ArrayList的使用

array 數組效率最高,但容量固定,無法動態改變,ArrayList容量可以動態增長,但犧牲了效率。

十七、應儘可能避免使用內在的GET,SET方法

像C++一樣的編程語言,通常會使用Get方法(例如 i = getCount())去取代直接訪問這個屬性(i=mCount)。這在C++編程裏面是一個很好的習慣,因爲編譯器會把訪問方式設置爲Inline,並且如果想約束或調試屬性訪問,你只需要在任何時候添加一些代碼。在Android編程中,這不是一個很不好的主意。虛方法的調用會產生很多代價,比實例屬性查詢的代價還要多。我們應該在外部調用時使用Get和Set函數,但是在內部調用時,我們應該直接調用。

十八、儘量使用基本數據類型代替對象

 

十九、單線程應儘量使用 HashMap, ArrayList,除非必要,否則不推薦使用HashTable,Vector,她們使用了同步機制,而降低了性能

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章