一、引子
一般來說,最好能重用對象而不是每次需要的時候就創建一個相同功能的新對象,特別是當對象不可變時,它始終可以被重用的。重用對象對程序性能起到重要作用。
二、重用不可變對象
對於同時提供了靜態工廠方法和構造器的不可變類,通常可以使用靜態工廠方法而不是構造器,以避免創建不必要的對象。
Boolean b1 = Boolean.valueOf("test"); // 使用靜態工廠方法(good)
Boolean b2 = new Boolean("test"); // 使用構造器(bad)
三、重用不會被修改的可變對象
下面的例子業務為:檢驗某個人是否出生於1946年 ~ 1964年期間。
/*
* 改進前
*/
public class Person {
private Date birthDate = new Date();
public boolean isBabyBoomer() {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
calendar.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
Date boomStart = calendar.getTime();
calendar.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
Date boomEnd = calendar.getTime();
return birthDate.compareTo(boomStart) >= 0 && birthDate.compareTo(boomEnd) < 0;
}
}
/*
* 改進後
*/
public class Person2 {
private Date birthDate = new Date();
private static Date BOOM_START;
private static Date BOOM_END;
static {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
calendar.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = calendar.getTime();
calendar.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = calendar.getTime();
}
public boolean isBabyBoomer() {
return birthDate.compareTo(BOOM_START) >= 0 && birthDate.compareTo(BOOM_END) < 0;
}
}
查看本欄目
改進前每調用一次isBabyBoomer都會創建一個Calendar,TimeZone,Date對象,改進後的程序只會在初始化的時候創建這些對象一次。如果isBabyBoomer方法被頻繁的調用,那麼將會顯著地提高性能。
四、自動裝箱和拆箱
看一下下面這個小程序,不知道你能不能發現什麼問題?
public class Client {
public static void main(String[] args) {
long start = System.currentTimeMillis();
Long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i;
}
long end = System.currentTimeMillis();
System.out.println(">>>>>>>>>>Total spent time: " + (end - start) / 1000 + "s");
}
}
因為sum定義為Long類型,導致這個程序創建了很多不必要的對象,每次往Long sum中增加long i 時都會構建一個實例。
結論:要優先使用基本數據類型而不是裝箱基本類型,要當心無意識的自動裝箱。
作者:csdn博客 zdp072