我学习有效的Java并在书中,关于避免创建不必要的对象的约书亚·布洛克会谈的第5项。一个示例演示可变Date对象,它们的值一经计算就不会被修改。有效的Java - 相同的方法调用时,尽管创建多个实例
这里的“坏习惯”:
public Person(Date birthDate) {
this.birthDate = new Date(birthDate.getTime());
}
// DON'T DO THIS!
public boolean isBabyBoomer() {
// Unnecessary allocation of expensive object
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
Date boomStart = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
Date boomEnd = gmtCal.getTime();
return birthDate.compareTo(boomStart) >= 0
&& birthDate.compareTo(boomEnd) < 0;
}
的isBabyBoomer方法不必要地创建了一个新的日历,时区和两个Date每次被调用的时刻 - 这显然对我来说很有意义。
这里改进的代码:创建只有一次,当它被初始化
public Person(Date birthDate) {
this.birthDate = new Date(birthDate.getTime());
}
/**
* The starting and ending dates of the baby boom.
*/
private static final Date BOOM_START;
private static final Date BOOM_END;
static {
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = gmtCal.getTime();
}
public boolean isBabyBoomer() {
return birthDate.compareTo(BOOM_START) >= 0
&& birthDate.compareTo(BOOM_END) < 0;
}
日历,时区和日期的情况。 布洛赫解释道,这会导致显著的性能提升,如果该方法isBabyBoomer()
被频繁调用。
在他的机器:
坏的版本:32,000毫秒1000万调用
改进版:130MS 1000万调用
但是当我运行在我的系统示例中的表现是完全一样的( 14毫秒)。 这是一个编译器功能,实例只创建一次?
编辑:
这里是我的标杆:
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.set(1960, Calendar.JANUARY, 1, 1, 1, 0);
Person p = new Person(cal.getTime());
long startTime = System.nanoTime();
for (int i = 0; i < 10000000; i++) {
p.isBabyBoomer();
}
long stopTime = System.nanoTime();
long elapsedTime = stopTime - startTime;
double mseconds = (double) elapsedTime/1000000.0;
System.out.println(mseconds);
}
干杯,马库斯
您可能需要阅读:http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java – 2013-02-09 21:33:08
与现代JVM我希望有与新推出的多种genreation GC技术没有什么不同。 – 2013-02-09 21:36:12
是否**你也调用它1000万次(循环中)(检查循环前后的时间)?如果你只运行过一次,它们都会创建一次对象(虽然在不同的时间),但实际上并不多。 – Dukeling 2013-02-09 21:38:34