程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java代碼優化細節

Java代碼優化細節

編輯:關於JAVA

Java代碼優化細節。本站提示廣大學習愛好者:(Java代碼優化細節)文章只能為提供參考,不一定能成為您想要的結果。以下是Java代碼優化細節正文


代碼優化細節 

1、盡可能指定類、辦法的final潤飾符
帶有final潤飾符的類是弗成派生的。在Java焦點API中,有很多運用final的例子,例如java.lang.String,全部類都是final的。為類指定final潤飾符可讓類弗成以被繼續,為辦法指定final潤飾符可讓辦法弗成以被重寫。假如指定了一個類為final,則該類一切的辦法都是final的。Java編譯器會尋覓機遇內聯一切的final辦法,內聯關於晉升Java運轉效力感化嚴重 

2、盡可能重用對象 
特殊是String對象的應用,湧現字符串聯接時應當應用StringBuilder/StringBuffer取代。因為Java虛擬機不只要花時光生成對象,今後能夠還須要花時光對這些對象停止渣滓收受接管和處置,是以,生成過量的對象將會給法式的機能帶來很年夜的影響。 

3、盡量應用部分變量
 挪用辦法時傳遞的參數和在挪用中創立的暫時變量都保留在棧中速度較快,其他變量,如靜態變量、實例變量等,都在堆中創立,速度較慢。別的,棧中創立的變量,跟著辦法的運轉停止,這些內容就沒了,不須要額定的渣滓收受接管。 

4、實時封閉流 
Java編程進程中,停止數據庫銜接、I/O流操作時務必當心,在應用終了後,實時封閉以釋放資本。由於對這些年夜對象的操作會形成體系年夜的開支,稍有失慎,將會招致嚴重的效果。 

5、盡可能削減對變量的反復盤算
明白一個概念,對辦法的挪用,即便辦法中只要一句語句,也是有消費的,包含創立棧幀、挪用辦法時掩護現場、挪用辦法終了時恢復現場等。所以例以下面的操作: 

for(inti = 0; i < list.size(); i++)
{...}建議調換為:

for(inti = 0, length = list.size(); i < length; i++)
{...}
如許,在list.size()很年夜的時刻,就削減了許多的消費 

6、盡可能采取懶加載的戰略,即在須要的時刻才創立

7、慎用異常 
異常對機能晦氣。拋出異常起首要創立一個新的對象,Throwable接口的結構函數挪用名為fillInStackTrace()的當地同步辦法,fillInStackTrace()辦法檢討客棧,搜集挪用跟蹤信息。只需有異常被拋出,Java虛擬機就必需調劑挪用客棧,由於在處置進程中創立了一個新的對象。異常只能用於毛病處置,不該該用來掌握法式流程。 

8、不要在輪回中應用try…catch…,應當把其放在最外層

依據網友們提出的看法,這一點我以為值得商議 

9、假如能估量到待添加的內容長度,為底層以數組方法完成的聚集、對象類指定初始長度 
好比ArrayList、LinkedLlist、StringBuilder、StringBuffer、HashMap、HashSet等等,以StringBuilder為例: 
(1)StringBuilder()      // 默許分派16個字符的空間 
(2)StringBuilder(int size)  // 默許分派size個字符的空間 
(3)StringBuilder(String str) // 默許分派16個字符+str.length()個字符空間 
可以經由過程類(這裡指的不只僅是下面的StringBuilder)的結構函數來設定它的初始化容量,如許可以顯著地晉升機能。好比StringBuilder吧,length表現以後的StringBuilder能堅持的字符數目。由於當StringBuilder到達最年夜容量的時刻,它會將本身容量增長到以後的2倍再加2,不管什麼時候只需StringBuilder到達它的最年夜容量,它就不能不創立一個新的字符數組然後將舊的字符數組內容拷貝到新字符數組中—-這是非常消耗機能的一個操作。試想,假如能預估到字符數組中年夜概要寄存5000個字符而不指定長度,最接近5000的2次冪是4096,每次擴容加的2不論,那末:
(1)在4096 的基本上,再請求8194個年夜小的字符數組,加起來相當於一次請求了12290個年夜小的字符數組,假如一開端能指定5000個年夜小的字符數組,就節儉了一倍以上的空間 
(2)把本來的4096個字符拷貝到新的的字符數組中去 
如許,既糟蹋內存空間又下降代碼運轉效力。所以,給底層以數組完成的聚集、對象類設置一個公道的初始化容量是錯不了的,這會帶來吹糠見米的後果。然則,留意,像HashMap這類是以數組+鏈表完成的聚集,別把初始年夜小和你估量的年夜小設置得一樣,由於一個table上只銜接一個對象的能夠性簡直為0。初始年夜小建議設置為2的N次冪,假如能估量到有2000個元素,設置成new HashMap(128)、new HashMap(256)都可以。 

10、當復制年夜量數據時,應用System.arraycopy()敕令 

11、乘法和除法應用移位操作 

12、輪回內不要赓續創立對象援用 

例如: 

for(inti = 1; i <= count; i++)
{
 Object obj = newObject(); 
}

這類做法會招致內存中有count份Object對象援用存在,count很年夜的話,就消耗內存了,建議為改成: 

Object obj = null;
for(inti = 0; i <= count; i++)
{
 obj = newObject();
}

 如許的話,內存中只要一份Object對象援用,每次new Object()的時刻,Object對象援用指向分歧的Object而已,然則內存中只要一份,如許就年夜年夜節儉了內存空間了。 

13、基於效力和類型檢討的斟酌,應當盡量應用array,沒法肯定數組年夜小時才應用ArrayList

14、盡可能應用HashMap、ArrayList、StringBuilder,除非線程平安須要,不然不推舉應用Hashtable、Vector、StringBuffer,後三者因為應用同步機制而招致了機能開支 

15、不要將數組聲明為public static final 

由於這毫有意義,如許只是界說了援用為static final,數組的內容照樣可以隨便轉變的,將數組聲明為public更是一個平安破綻,這意味著這個數組可以被內部類所轉變 

16、盡可能在適合的場所應用單例
應用單例可以加重加載的累贅、延長加載的時光、進步加載的效力,但其實不是一切處所都實用於單例,簡略來講,單例重要實用於以下三個方面: 
(1)掌握資本的應用,經由過程線程同步來掌握資本的並發拜訪 
(2)掌握實例的發生,以到達勤儉資本的目標 
(3)掌握數據的同享,在不樹立直接聯系關系的前提下,讓多個不相干的過程或線程之間完成通訊 

17、盡可能防止隨便應用靜態變量 

public class A
{
 private static B b = newB(); 
} 

此時靜態變量b的性命周期與A類雷同,假如A類不被卸載,那末援用B指向的B對象會常駐內存,直到法式終止 

18、實時消除不再須要的會話 
為了消除不再運動的會話,很多運用辦事器都有默許的會話超不時間,普通為30分鐘。當運用辦事器須要保留更多的會話時,假如內存缺乏,那末操作體系會把部門數據轉移到磁盤,運用辦事器也能夠依據MRU(比來最頻仍應用)算法把部門不活潑的會話轉儲到磁盤,乃至能夠拋出內存缺乏的異常。假如會話要被轉儲到磁盤,那末必需要先被序列化,在年夜范圍集群中,對對象停止序列化的價值是很昂貴的。是以,當會話不再須要時,應該實時挪用HttpSession的invalidate()辦法消除會話。 

19、完成RandomAccess接口的聚集好比ArrayList,應該應用最通俗的for輪回而不是foreach輪回來遍歷 
這是JDK推舉給用戶的。JDK API關於RandomAccess接口的說明是:完成RandomAccess接口用來注解其支撐疾速隨機拜訪,此接口的重要目標是許可普通的算法更改其行動,從而將其運用到隨機或持續拜訪列表時能供給優越的機能。現實經歷注解,完成RandomAccess接口的類實例,假設是隨機拜訪的,應用通俗for輪回效力將高於應用foreach輪回;反過去,假如是次序拜訪的,則應用Iterator會效力更高。可使用相似以下的代碼作斷定: 

if(list instanceofRandomAccess)
{
 for(inti = 0; i < list.size(); i++){}
}
else
{
 Iterator<?> iterator = list.iterable();
 while(iterator.hasNext()){iterator.next()}
} 

foreach輪回的底層完成道理就是迭代器Iterator,所今後半句”反過去,假如是次序拜訪的,則應用Iterator會效力更高”的意思就是次序拜訪的那些類實例,應用foreach輪回去遍歷。 

20、應用同步代碼塊替換同步辦法 
這點在多線程模塊中的synchronized鎖辦法塊一文中曾經講得很清晰了,除非能肯定一全部辦法都是須要停止同步的,不然盡可能應用同步代碼塊,防止對那些不須要停止同步的代碼也停止了同步,影響了代碼履行效力。 

21、將常量聲明為static final,並以年夜寫定名
如許在編譯時代便可以把這些內容放入常量池中,防止運轉時代盤算生成常量的值。別的,將常量的名字以年夜寫定名也能夠便利辨別出常量與變量 

22、不要創立一些不應用的對象,不要導入一些不應用的類 

這毫有意義,假如代碼中湧現”The value of the local variable i is not used”、”The import java.util is never used”,那末請刪除這些無用的內容 

23、法式運轉進程中防止應用反射
關於,請拜見反射。反射是Java供給給用戶一個很壯大的功效,功效壯大常常意味著效力不高。不建議在法式運轉進程中應用特別是頻仍應用反射機制,特殊是Method的invoke辦法,假如確切有需要,一種建議性的做法是將那些須要經由過程反射加載的類在項目啟動的時刻經由過程反射實例化出一個對象並放入內存—-用戶只關懷和對端交互的時刻獲得最快的呼應速度,其實不關懷對真個項目啟動花多久時光。 

24、應用數據庫銜接池和線程池
這兩個池都是用於重用對象的,前者可以免頻仍地翻開和封閉銜接,後者可以免頻仍地創立和燒毀線程 

25、應用帶緩沖的輸出輸入流停止IO操作

帶緩沖的輸出輸入流,即BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream,這可以極年夜地晉升IO效力 

26、次序拔出和隨機拜訪比擬多的場景應用ArrayList,元素刪除和中央拔出比擬多的場景應用LinkedList 

這個,懂得ArrayList和LinkedList的道理就曉得了 

27、不要讓public辦法中有太多的形參 

public辦法即對外供給的辦法,假如給這些辦法太多形參的話重要有兩點害處: 

1)、違背了面向對象的編程思惟,Java講究一切都是對象,太多的形參,和面向對象的編程思惟其實不契合 
2)、參數太多必將招致辦法挪用的失足幾率增長 
至於這個”太多”指的是若干個,3、4個吧。好比我們用JDBC寫一個insertStudentInfo辦法,有10個先生信息字段要插如Student表中,可以把這10個參數封裝在一個實體類中,作為insert辦法的形參 

28、字符串變量和字符串常量equals的時刻將字符串常量寫在後面
這是一個比擬罕見的小技能了,假如有以下代碼: 

String str = "123";
if(str.equals("123"))
{
 ...
} 

建議修正為: 

String str = "123";
if("123".equals(str))
{
 ...
} 

這麼做重要是可以免空指針異常 

32、不要對超越規模的根本數據類型做向下強迫轉型 

33、把一個根本數據類型轉為字符串,根本數據類型.toString()是最快的方法、String.valueOf(數據)次之、數據+”"最慢 
把一個根本數據類型轉為普通有三種方法,我有一個Integer型數據i,可使用i.toString()、String.valueOf(i)、i+”"三種方法,三種方法的效力若何,看一個測試: 

publicstatic void main(String[] args)
{
 intloopTime = 50000;
 Integer i = 0;
 longstartTime = System.currentTimeMillis();
 for(intj = 0; j < loopTime; j++)
 {
 String str = String.valueOf(i);
 } 
 System.out.println("String.valueOf():"+ (System.currentTimeMillis() - startTime) + "ms");
 startTime = System.currentTimeMillis();
 for(intj = 0; j < loopTime; j++)
 {
 String str = i.toString();
 } 
 System.out.println("Integer.toString():"+ (System.currentTimeMillis() - startTime) + "ms");
 startTime = System.currentTimeMillis();
 for(intj = 0; j < loopTime; j++)
 {
 String str = i + "";
 } 
 System.out.println("i + \"\":" + (System.currentTimeMillis() - startTime) + "ms");
}

 運轉成果為: 

String.valueOf():11ms
Integer.toString():5ms
i + "":25ms 

所以今後碰到把一個根本數據類型轉為String的時刻,優先斟酌應用toString()辦法。至於為何,很簡略: 
1、String.valueOf()辦法底層挪用了Integer.toString()辦法,然則會在挪用前做空斷定 
2、Integer.toString()辦法就不說了,直接挪用了
3、i + “”底層應用了StringBuilder完成,先用append辦法拼接,再用toString()辦法獲得字符串 
三者比較上去,顯著是2最快、1次之、3最慢

以上就是本文的全體內容,願望對年夜家的進修有所贊助,也願望年夜家多多支撐。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved