在实际开发中,重复使用同一个对象要比每次需要的时候就创建一个对象要好的多;
作为一个比较极端的反面例子,看下面这个语句:
String s = new String("haha");
改语句每次被执行时都会创建一个新的String实例,如果这种用法是在一个循环中,或者是在一个被频繁调用的方法中,将会有成千上万个String实例被创建,这样的做法是没有必要的,可改进成如下这样:
String s = “haha”;
这个版本只使用一个String实例,而不是每次被执行的时候都创建了一个实例。对于在同一个虚拟中,运行的代码,只要包含相同的字符串字面常量,则改对象就会被重用。
除了重用非可变的对象外,对于那些已知不会被修改的可变对象,也是可以重用它们,看个比较常见的例子:
1 public class Person{ 2 private final Date birthDate; 3 4 public Person(Date birthDate){ 5 this.birthDate = birthDate; 6 } 7 8 public boolean isBabyBoomer(){ 9 Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); 10 11 gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0); 12 Date boomStart = gmtCal.getTime(); 13 14 gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0); 15 Date boomEnd = gmtCal.getTime(); 16 17 return birthDate.compareTo(boomStart) >= 0 && birthDate.compareTo(boomEnd) < 0; 18 } 19 20 }
isBabyBoomer每次被调用的时候,都会创建一个新的Calendar, 一个新的TimeZone,两个新的Date对象,这是不必要的,下面的版本使用一个静态的初始化器,避免了上面例子的低效:
1 public class Person{ 2 private final Date birthDate; 3 4 public Person(Date birthDate){ 5 this.birthDate = birthDate; 6 } 7 8 private static final Date BOOM_START; 9 private static final Date BOOM_END; 10 11 static{ 12 Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); 13 14 gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0); 15 BOOM_START = gmtCal.getTime(); 16 17 gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0); 18 BOOM_END = gmtCal.getTime(); 19 } 20 21 public boolean isBabyBoomer(){ 22 return birthDate.compareTo(boomStart) >= 0 && birthDate.compareTo(boomEnd) < 0; 23 } 24 25 }
改进版本的Person类仅在初始化时刻创建Calendar、TimeZone和Date实例一次,而不是在每次isBadyBoomer被调用的时候创建它们。