您的位置:首页 > 其它

(5):避免创造不必要对象

2017-03-29 16:44 113 查看
一般来说,最好是能重用已有的对象,而不是每次有需要的时候就去创建一个相同功能的对象。比较下面两个例子

(1).String s1 = “string1”;

(2).String s2 = new String(“string1”);

(2)比(1)多创造出了许多不必要的对象。由于String被实现为不可变对象,JVM底层将其实现为常量池,既所有值等于"string1" 的String对象实例共享同一对象地址,而且还可以保证,对于所有在同一JVM中运行的代码,只要他们包含相同的字符串字面常量,该对象就会被重用。所以(1)可以重用已经存在的“string1”对象。而(2)却开辟了新的内存,这就大大浪费了内存。

除了重用不可变的对象之外,也可以重用那些已知不会被修改的对象。仔细观察下面两个例子:

public class Person{
private Date birthDate;
//判断是否是婴儿潮出生的人
public boolean isBabyBoomer(){
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(“GMT”));
//婴儿潮开始时间
cal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
Date boomStart = cal.getTime();
//婴儿潮结束时间
cal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
Date boomEnd = cal.getTime();
return birthDate.compareTo(boomStart) >= 0 && birthDate.compareTo(boomEnd) < 0;
}
}
每次调用isBabyBoomer()方式时,都需要创建Calendar,TimeZone,boomStart和boomEnd四个对象,测试调用该方法1000万次,大约耗时32秒。

Calendar,TimeZone,boomStart和boomEnd四个对象是所有调用者共用的对象,只需创建一份即可,改进之后代码如下:

public class Person{
private Date birthDate;
private static final Date BOOM_START;
private static final Date BOOM_END;
static{
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(“GMT”));
//婴儿潮开始时间
cal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = cal.getTime();
//婴儿潮结束时间
cal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = cal.getTime();
}
//判断是否是婴儿潮出生的人
public boolean isBabyBoomer(){
return birthDate.compareTo(BOOM_START) >= 0 && birthDate.compareTo(BOOM_END) < 0;
}
}

这样Person类只在初始化时创建Calendar,TimeZone,boomStart和boomEnd四个对象一次,如果isBabyBoomer()被频繁调用,性能就可以得到明星提高。

在java 1.5版本中,有一种创建多余对象的方法,称作自动装箱。看下面的例子

public CalculateInt{
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类型,而不是原始类型的long,因此总共进行了2的31次方不必要的类型自动封装(将原始类型的long封装为Long),总共耗时大约43秒。

将sum声明的由Long类型改为原始类型的long,由于省去了2的31次方不必要的类型自动封装,程序大概耗时6秒,性能提高7倍。所以要尽量使用基本类型。

最后要注意但重用对象而付出的代价远远大于创建对象的代价时,这条建议就未必适用了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: