首頁 > Java > java教程 > 主體

Java開發程式碼效能最佳化總結

黄舟
發布: 2017-02-06 13:11:47
原創
1390 人瀏覽過

程式碼優化,可能說起來一些人覺得沒用.可是我覺得應該平時開發過程中,就盡量要求自己,養成良好習慣,一個個小的優化點,積攢起來絕對是有大幅度效率提升的。好了,將平時看到用到總結的分享給大家。


程式碼最佳化的目標


1減小程式碼體積

2提高整個系統的運作效率



帶有final修飾的類別是不可派生的。在Java核心API中,有許多應用final的例子,例如java.lang.String,整個類別都是final的.為類別指定final修飾符可以讓類別不可以被繼承,為方法指定final可以讓方法不可以被重寫。如果指定一個類別為fianl,則該類別的所有方法都是final的。 Java編譯器會尋找機會內嵌所有的final方法,內嵌對於提升Java運作效率作用重大,具體參考Java執行期最佳化。此舉能夠提升性能平均50%。


2盡量重複使用物件


特別是 String 物件的使用,出現字串連線時應使用 StringBuilder/StringBuffer取代。由於 Java 虛擬機不僅要花時間產生對象,以後可能還需要花時間對這些對象進行垃圾回收和處理,因此,產生過多的對象將會對程式的效能帶來很大的影響。


3盡可能使用局部物件


呼叫方法時傳遞的參數以及在呼叫中創建的臨時變數都保存在堆疊中速度較快,其他變數,如靜態變數、實例變數等,都在堆中創建,速度較慢。 另外,堆疊中建立的變量,隨著方法的運作結束,這些內容就沒了,不需要額外的垃圾回收。


4及時關閉流


Java編程過程中,進行資料庫連接、I/O流操作時務必小心,在使用完畢後,及時關閉以釋放資源。因為這些大物件的操作會造成系統大的開銷,稍有不慎,將會導致嚴重的後果。


5盡量減少對變數的重複計算


明確一個概念,對方法的調用,即使方法中只有一句語句,也是有幀消耗的,包括創建棧、調用方法時保護現場、調用方法完畢時恢復現場等。所以例如下面的操作:

for (int i = 0; i < list.size(); i++)
{...}
登入後複製

建議替換為:

for (int i = 0, int length = list.size(); i < length; i++)
{...}
登入後複製

這樣,在list.size()很大的時候,就減少了很多的消耗

6 盡量採用懶加載的策略,即在需要的時間才創建

例如:

String str = "aaa";if (i == 1)
{
list.add(str);
}
登入後複製

建議替換為:

if (i == 1)
{String str = "aaa";
list.add(str);
}
登入後複製

7 慎用異常


異常對性能不利。拋出例外首先要建立一個新的對象, Throwable 介面的建構子呼叫名為 fillInStackTrace() 的本機同步方法, fillInStackTrace() 方法檢查堆疊,收集呼叫追蹤資訊。只要有異常被拋出, Java 虛擬機就必須調整呼叫堆疊,因為在處理過程中建立了一個新的物件。異常只能用於錯誤處理,不應該用來控製程式流程。


8 不要在循環中使用 try…catch… ,應將其放在最外

 

除非不得已。如果毫無理由地這麼寫了,只要你的領導資深一點、有強迫症一點,八成就要罵你為什麼寫出這種垃圾代碼來了

9 如果能估計到待添加的內容長度,為底層以陣列方式實現的集合、工具類別指定初始長度


例如ArrayList、LinkedLlist、StringBuilder、StringBuffer、HashMap、HashSet等等,以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 乘法和除法使用移位操作


例如:

for (val = 0; val < 100000; val += 5)
{
a = val * 8;
b = val / 2;
}
登入後複製

用移位操作可以极大地提高性能,因为在计算机底层,对位的操作是最方便、最快的,因此建议修改为:

for (val = 0; val < 100000; val += 5)
{
a = val << 3;
b = val >> 1;
}
登入後複製

移位操作虽然快,但是可能会使代码不太好理解,因此最好加上相应的注释。

12 循环内不要不断创建对象引用


例如:

for (int i = 1; i <= count; i++)
{Object obj = new Object();
}
登入後複製

这种做法会导致内存中有count份Object对象引用存在,count很大的话,就耗费内存了,建议为改为:Object obj = null;for (int i = 0; i <= count; i++) { obj = new Object(); }
这样的话,内存中只有一份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 尽量避免随意使用静态变量


要知道,当某个对象被定义为 static 的变量所引用,那么 gc 通常是不会回收这个对象所占有的堆内存的,如:

public class A{private static B b = new B();
}
登入後複製

以上就是Java开发代码性能优化总结的内容,更多相关内容请关注PHP中文网(www.php.cn)!


來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板