一般来说,我们最好能够重用对象,而不是每次需要的时候都去创建一个相同的对象。
重用对象即快速,又流行,如果对象时不可变的,它就始终可以被重用。
下面有一个反面的例子:
String s=new String("string");
该语句每次被执行都会创建一个新的String实例,但是这是不必要的,传递给String构造器的参数本身就是一个String实例,
功能方面等同于构造器创建的所有对象,如果这是一个被频繁调用的方法中,就会创建出成千上万不必要的String实例。
可以改进为如下所示:
String s="String";
除了重用不可变的对象之外,也可以重用那些已知不会被修改的可变对象。
下面是一个反面的例子:
public class Person { private Date birthDate; public boolean isBabyBoomer(){ 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每次被调用,都会创建一个Calendar,一个TimeZone和俩个Date实例,这是完全不必要的。
下面使用一个静态初始化器,避免了这种低效的情况:
public class Person { private static Date birthDate; 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方法永远不被调用,那就没有必要初始化那些BOOM_START和BOOM_END,
我们可以通过延迟加载,来避免这个问题,把BOOT_START和BOOM_END的初始化,放在第一次调用isBabyBoomer方法的时候进行。
在JAVA1.5的发型版本中,加入了自动装箱拆箱,如果不小心使用,也会导致创建不必要的对象,如下:
public static void main(String args[]){ Long sum=0L; for(long i=0;i<Integer.MAX_VALUE;i++){ sum+=i; } System.out.println(sum); }上诉代码是正确的代码,但是比实际情况要慢很多,只是因为将sum声明成了Long,就意味着要创建大约2的32次方个多余的Long实例,所以导致了导致了计算较慢,如果把Long改成long就会快很多了。