本文主题:什么时候、如何避免创建对象?
重复使用同一个对象,而不是每次需要的时候就创建一个功能上等价的新对象,通常前者更为合适。重用方式既快速,也更为流行。如果一个对象是不可变的,那么它总是可以被重用。但是,不要错误地认为:“创建对象的代价是非常昂贵的,我们应该要尽可能地避免创建对象”,而应该是:“当你可以重用一个已有的对象时,请不要创建对象;当你应该创建一个新的对象时,请不要重用已有的对象 ”。由于小对象的构造函数只做很少量的工作,所以小对象的创建和回收动作是很廉价的,特别是在现代的JVM实现上更是如此。
下面引用一个例子来说明:当创建一个高昂的实例时候,如何优化
优化前:
public class EffectiveJavaStudyTest {
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
Person person=new Person(new Date());
System.out.println(person.isBabyBoomer());
}
}
}
class Person{
private final Date brithDate;
public Person(Date brithDate) {
this.brithDate = brithDate;
}
public boolean isBabyBoomer(){
Calendar calendar=Calendar.getInstance();
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 brithDate.compareTo(boomStart)>=0 && brithDate.compareTo(boomEnd) <0;
}
}
优化后:
public class EffectiveJavaStudyTest {
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
Person person=new Person(new Date());
System.out.println(person.isBabyBoomer());
}
}
}
class Person{
private final Date brithDate;
private static final Date BOOMSTART;
private static final Date BOOMEND;
static {
Calendar calendar=Calendar.getInstance();
calendar.set(1946,Calendar.JANUARY,1,0,0,0);
BOOMSTART=calendar.getTime();
calendar.set(1965,Calendar.JANUARY,1,0,0,0);
BOOMEND=calendar.getTime();
}
public Person(Date brithDate) {
this.brithDate = brithDate;
}
public boolean isBabyBoomer(){
return brithDate.compareTo(BOOMSTART)>=0 && brithDate.compareTo(BOOMEND) <0;
}
}
由于Calendar类实例的创建代价高昂,所以经过改良后的代码,在main中循环调用时,只实例化一次,从而提高了性能。
总结:对应开头,在创建高昂的实例,并实例需要被重用时,应优先考虑避免重复创建对象