通過使用一些輔助性工具來找到程式中的瓶頸,然後就可以對瓶頸部分的程式碼進行優化。一般有兩種方案:即優化程式碼或更改設計方法。我們一般會選擇後者,因為不去呼叫以下程式碼要比呼叫一些優化的程式碼更能提高程式的效能。而一個設計良好的程式能夠精簡程式碼,從而提高效能。
下面將提供一些在JAVA程式的設計和編碼中,為了能夠提高JAVA程式的效能,而經常採用的一些方法和技巧。
1.物件的生成和大小的調整。
JAVA程式設計中一個普遍的問題就是沒有好好的利用JAVA語言本身提供的函式,從而常常會生成大量的物件(或例項)。由於系統不僅要花時間生成物件,以後可能還需花時間對這些物件進行垃圾回收和處理。因此,生成過多的物件將會給程式的效能帶來很大的影響。
例1:關於String ,StringBuffer,+和append
JAVA語言提供了對於String型別變數的操作。但如果使用不當,會給程式的效能帶來影響。如下面的語句:
String name=new String("HuangWeiFeng");
tln(name+"is my name");
看似已經很精簡了,其實並非如此。為了生成二進位制的程式碼,要進行如下的步驟和操作:
(1) 生成新的字串 new String(STR_1);
(2) 複製該字串;
(3) 載入字串常量"HuangWeiFeng"(STR_2);
(4) 呼叫字串的構架器(Constructor);
(5) 儲存該字串到陣列中(從位置0開始);
(6) 從tStream類中得到靜態的out變數;
(7) 生成新的字串緩衝變數new StringBuffer(STR_BUF_1);
(8) 複製該字串緩衝變數;
(9) 呼叫字串緩衝的構架器(Constructor);
(10) 儲存該字串緩衝到陣列中(從位置1開始);
(11) 以STR_1為引數,呼叫字串緩衝(StringBuffer)類中的append方法;
(12) 載入字串常量"is my name"(STR_3);
(13) 以STR_3為引數,呼叫字串緩衝(StringBuffer)類中的append方法;
(14) 對於STR_BUF_1執行toString命令;
(15) 呼叫out變數中的println方法,輸出結果。
由此可以看出,這兩行簡單的程式碼,就生成了STR_1,STR_2,STR_3,STR_4和STR_BUF_1五個物件變數。這些生成的類的例項一般都存放在堆中。堆要對所有類的超類,類的例項進行初始化,同時還要呼叫類極其每個超類的構架器。而這些操作都是非常消耗系統資源的。因此,對物件的生成進行限制,是完全有必要的。
經修改,上面的程式碼可以用如下的程式碼來替換。
StringBuffer name=new StringBuffer("HuangWeiFeng");
tln(nd("is my name.")ring());
系統將進行如下的操作:
(1) 生成新的字串緩衝變數new StringBuffer(STR_BUF_1);
(2) 複製該字串緩衝變數;
(3) 載入字串常量"HuangWeiFeng"(STR_1);
(4) 呼叫字串緩衝的構架器(Constructor);
(5) 儲存該字串緩衝到陣列中(從位置1開始);
(6) 從tStream類中得到靜態的out變數;
(7) 載入STR_BUF_1;
(8) 載入字串常量"is my name"(STR_2);
(9) 以STR_2為引數,呼叫字串緩衝(StringBuffer)例項中的append方法;
(10) 對於STR_BUF_1執行toString命令(STR_3);
(11)呼叫out變數中的println方法,輸出結果。
由此可以看出,經過改進後的程式碼只生成了四個物件變數:STR_1,STR_2,STR_3和STR_BUF_1.你可能覺得少生成一個物件不會對程式的效能有很大的提高。但下面的程式碼段2的執行速度將是程式碼段1的2倍。因為程式碼段1生成了八個物件,而程式碼段2只生成了四個物件。
程式碼段1:
String name= new StringBuffer("HuangWeiFeng");
name+="is my";
name+="name";
程式碼段2:
StringBuffer name=new StringBuffer("HuangWeiFeng");
nd("is my");
nd("name.")ring();
因此,充分的利用JAVA提供的庫函式來優化程式,對提高JAVA程式的效能時非常重要的.其注意點主要有如下幾方面;
(1) 儘可能的使用靜態變數(Static Class Variables)
如果類中的變數不會隨他的例項而變化,就可以定義為靜態變數,從而使他所有的例項都共享這個變數。
例:
public class foo
{
SomeObject so=new SomeObject();
}
就可以定義為:
public class foo
{
static SomeObject so=new SomeObject();
}
(2) 不要對已生成的物件作過多的改變。
對於一些類(如:String類)來講,寧願在重新生成一個新的物件例項,而不應該修改已經生成的物件例項。
例:
String name="Huang";
name="Wei";
name="Feng";
上述程式碼生成了三個String型別的物件例項。而前兩個馬上就需要系統進行垃圾回收處理。如果要對字串進行連線的操作,效能將得更差,因為系統將不得為此生成更多得臨時變數,如上例1所示。
(3) 生成物件時,要分配給它合理的空間和大小JAVA中的很多類都有它的預設的空間分配大小。對於StringBuffer類來講,預設的分配空間大小是16個字元。如果在程式中使用StringBuffer的空間大小不是16個字元,那麼就必須進行正確的初始化。
(4) 避免生成不太使用或生命週期短的物件或變數。對於這種情況,因該定義一個物件緩衝池。以為管理一個物件緩衝池的開銷要比頻繁的.生成和回收物件的開銷小的多。
(5) 只在物件作用範圍內進行初始化。JAVA允許在程式碼的任何地方定義和初始化物件。這樣,就可以只在物件作用的範圍內進行初始化。從而節約系統的開銷。
例:
SomeObject so=new SomeObject();
If(x==1) then
{
Foo=X();
}
可以修改為:
if(x==1) then
{
SomeObject so=new SomeObject();
Foo=X();
}
2.異常(Exceptions)
JAVA語言中提供了try/catch來發方便使用者捕捉異常,進行異常的處理。但是如果使用不當,也會給JAVA程式的效能帶來影響。因此,要注意以下兩點:
(1) 避免對應用程式的邏輯使用try/catch
如果可以用if,while等邏輯語句來處理,那麼就儘可能的不用try/catch語句。
(2) 重用異常
在必須要進行異常的處理時,要儘可能的重用已經存在的異常物件。以為在異常的處理中,生成一個異常物件要消耗掉大部分的時間。