張敬
摘 要程序編碼在整個軟件生命周期中是將軟件設(shè)計的結(jié)果轉(zhuǎn)換成計算機可運行的程序代碼的過程,也可以說是程序的內(nèi)在本質(zhì)。在實際項目中,代碼優(yōu)化至關(guān)重要。本文就是從代碼優(yōu)化的角度,介紹了一些優(yōu)化Java代碼的建議,包括盡量重用對象,使用局部變量等,還利用一些實例來說明和解釋優(yōu)化方法的有效性,可以使軟件性能得到提升,提高軟件的運行速度,減少運行時占用的內(nèi)存。
【關(guān)鍵詞】軟件性能 代碼優(yōu)化 Java
1 前言
當(dāng)今的軟件功能越來越復(fù)雜,需求也越來越多,隨之而來對軟件性能上的要求有時候是硬件不能完全解決的。很多實際的項目證明,如果在開發(fā)軟件時不注意軟件性能的優(yōu)化,雖然可能實現(xiàn)了要求的功能,但是也可能不會給用戶帶來很好的效益。因此,軟件的性能優(yōu)化一直是計算機開發(fā)過程中需要注意的問題,而代碼優(yōu)化是性能優(yōu)化其中重要的一個方面。一個優(yōu)秀的軟件系統(tǒng)應(yīng)該有一個優(yōu)化的代碼結(jié)構(gòu)。代碼優(yōu)化的目的是減小代碼體積,提高代碼運行的效率。但是可能有些人覺得沒用,改與不改對于代碼的運行效率有什么影響呢?如果項目著眼于盡快無BUG上線,那么此時代碼的細節(jié)可以不精打細磨;但是如果有足夠的時間開發(fā)、維護代碼,這時候就必須考慮每個可以優(yōu)化的細節(jié)了,一個一個細小的優(yōu)化點累積起來,對于代碼的運行效率絕對大有提升。
2 軟件性能的代碼優(yōu)化
2.1 軟件性能
軟件性能是軟件的一種非功能特性,它關(guān)注的不是軟件是否能夠完成特定的功能,而是在完成該功能時展示出來的及時性,是指一個軟件系統(tǒng)正確提供其服務(wù)的能力和效率,是軟件對用戶請求響應(yīng)速度在響應(yīng)時間、吞吐量、資源利用率和可用性等方面的度量。
2.2 代碼優(yōu)化
代碼優(yōu)化是指對程序代碼進行等價變換。等價的含義是使得變換后的代碼運行結(jié)果與變換前代碼運行結(jié)果相同。優(yōu)化的含義是最終生成的代碼短,時空效率優(yōu)化。優(yōu)化可以在編譯的各個階段進行,目標(biāo)是能生成更加高效的目標(biāo)代碼。
2.3 代碼優(yōu)化方法及實例應(yīng)用
2.3.1 盡量重用對象和盡可能使用局部變量
當(dāng)使用String對象時,出現(xiàn)字符串連接時應(yīng)該使用StringBuilder或StringBuffer代替。由于Java虛擬機不僅要花時間生成對象,以后可能還需要花時間對這些對象進行垃圾回收和處理,因此,生成過多的對象將會給程序的性能帶來很大的影響。調(diào)用方法時傳遞的參數(shù)以及在調(diào)用中創(chuàng)建的臨時變量都保存在棧中,因此速度較快,但是其他變量,如靜態(tài)變量、實例變量等,都在堆中創(chuàng)建,速度較慢。另外,棧中創(chuàng)建的變量,隨著方法的運行結(jié)束,不需要額外的垃圾回收;而在堆中創(chuàng)建的變量,需要進行額外回收。
2.3.2 盡量減少對變量的重復(fù)計算
在循環(huán)計算中,即使只有一條語句,對系統(tǒng)也是有消耗的,所以for循環(huán)中循環(huán)的大小可以在第一次進入循環(huán)時就聲明 ,不必每次循環(huán)都計算一遍。例如:
for (int i = 0; i < list.size(); i++)
{...}
建議替換為:
for (int i = 0, int length = list.size(); i < length; i++)
{...}
這樣在list.size()很大的時候,就減少了很多消耗。
2.3.3 盡量采用“懶加載”的策略,即在需要的時候才創(chuàng)建
舉個例子說明,就是:
String str = "aaa";
if (i == 1)
{list.add(str);}
建議替換為:
if (i == 1){String str = "aaa";list.add(str);}
2.3.4 循環(huán)內(nèi)不要不斷創(chuàng)建對象引用
for (int i = 1; i <= count; i++)
{Object obj = new Object();}
這種做法會導(dǎo)致內(nèi)存中有count個Object對象引用存在,count很大的時候,很耗費內(nèi)存,建議更改為:
Object obj = null;
for (int i = 0; i <= count; i++)
{ obj = new Object(); }
修改以后,內(nèi)存中只有一份Object對象引用。每次new新的Object()對象的時候,Object對象引用指向不同的Object,但是內(nèi)存中只有一份,這樣就大大節(jié)省了內(nèi)存空間。
2.3.5 使用帶緩沖的輸入輸出流進行I/O操作,并且及時關(guān)閉輸入輸出流
帶緩沖的輸入輸出流,即BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream,這可以極大地提升I/O效率。同時在Java編程過程中,進行數(shù)據(jù)庫連接、I/O流操作時,務(wù)必在使用完畢后及時關(guān)閉輸入輸出流,以釋放資源。因為對這些大對象的操作會造成大的開銷,不注意的話,可能會導(dǎo)致嚴(yán)重的后果。
2.3.6 不讓public方法中有太多的形參
public方法即對外提供的方法,如果給這些方法太多形參的話主要有兩點壞處:
a.違反了面向?qū)ο蟮木幊趟枷?,Java講求一切都是對象,太多的形參,和面向?qū)ο蟮木幊趟枷氩⒉黄鹾希?/p>
b.參數(shù)太多勢必導(dǎo)致方法調(diào)用的出錯概率增加。
比如我們用JDBC寫一個insertInfo方法,有9個信息字段要插如Person表中,可以把這9個參數(shù)封裝在一個實體類中,作為insertInfo方法的形參,而不是把這9個信息字段作為該方法的形參。。
2.3.7 字符串變量和字符串常量equals的時候?qū)⒆址A繉懺谇懊?/p>
這是一個比較常見的小技巧。如果有以下代碼:
String str = "678";
if (str.equals("678")) {...
}
建議修改為:
String str = "678";
if ("678".equals(str))
{...}
這么做主要是可以避免空指針異常。
2.3.8 基本數(shù)據(jù)類型轉(zhuǎn)為字符串,數(shù)據(jù).toString()是最快的方式、String.valueOf(數(shù)據(jù))次之、數(shù)據(jù)+””最慢
把基本數(shù)據(jù)類型轉(zhuǎn)為字符串有三種方式:一個Integer型數(shù)據(jù)i,可以使用i.toString()、String.valueOf(i)、i+”"三種方式,三種方式的效率,可以從這段代碼得到體現(xiàn):
public static void main(String[] args){
int loopTime = 50000;
Integer i = 0; long startTime = System.currentTimeMillis(); for (int j = 0; j < loopTime; j++)
{String str = String.valueOf(i);}
System.out.println("String.valueOf():" + (System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis(); for (int j = 0; j < loopTime; j++)
{String str = i.toString();}
System.out.println("Integer.toString():" + (System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis(); for (int j = 0; j < loopTime; j++)
{String str = i + "";}
System.out.println("i + \"\":" + (System.currentTimeMillis() - startTime) + "ms");}
運行結(jié)果為:
String.valueOf():11ms Integer.toString():5ms i + "":25ms
所以以后遇到把一個基本數(shù)據(jù)類型轉(zhuǎn)為String的時候,優(yōu)先考慮使用toString()方法。原因是:
(1)String.valueOf()方法底層調(diào)用了Integer.toString()方法,但是會在調(diào)用前做空判斷;
(2)Integer.toString()方法是直接調(diào)用;
(3)i + “”底層使用了StringBuilder實現(xiàn),先用append方法拼接,再用toString()方法獲取字符串。
三者對比下來,明顯是(2)最快、(1)次之、(3)最慢。
3 結(jié)束語
第二節(jié)介紹了八種優(yōu)化Java代碼的方法和實例,分析了進行優(yōu)化的方法,可以提高所編寫程序的性能,并增強代碼的可讀性和可擴展性。在具體的項目實踐中,這八種是最常用的方法,我們可以為具體的應(yīng)用程序在其中找到改善軟件性能的方法,進而提高用戶體驗,獲得更大的效益。
參考文獻
[1]馮宏華,徐瑩.C++應(yīng)用程序性能優(yōu)化[M].北京:電子工業(yè)出版社,2010.
[2]陳宇,李可.淺議Java程序優(yōu)化的幾種方法與成效[J].計算機光盤軟件與應(yīng)用,2013(07):60-61.
[3]錢宇虹.淺析Java程序I/O性能的改進策略[J].軟件工程師,2013(11):25-27.
[4]柳飛,陸明剛.Charlie Hunt,Binu John. Java性能優(yōu)化權(quán)威指南[M].北京:人民郵電出版社,2014.
作者單位
中國海洋大學(xué)信息科學(xué)與工程學(xué)院 山東省青島市 266100