第五条:避免创建不必要的对象

一般来说,我们最好能够重用对象,而不是每次需要的时候都去创建一个相同的对象。

重用对象即快速,又流行,如果对象时不可变的,它就始终可以被重用。

下面有一个反面的例子:

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就会快很多了。

猜你喜欢

转载自blog.csdn.net/qiuhao9527/article/details/80774303