您的位置:首页 > Web前端

effective java读书笔记5:避免创建不必要的对象

2017-01-19 00:00 411 查看
摘要: 创建和销毁对象

解读:如果不需要每次都创建一个相同功能的新对象,最好重用对象,因为有时候反复创建同样的对象是有代价的。

例如:

1、String 的初始化我们一般不会调用String s = new Sring("fs"),如果用在循环中,则会找出不必要的浪费(每次都会在堆中new一段空间出来)。而对于String s="fs"这种方式,jdk有常量池概念,反复地调用则会被重用。

2、每次调用isBabyBoomer方法的时候都会做重复的动作,实例化两个对象:boomStart 和boomEnd,而这两个对象实际上每次调用都是一样重复的,因此完全可以只保存一份实例即可,因此比较合理的作法是定义成两个静态的成员变量,第一次加载类的时候实例化,后续不在实例化了。

不合理的写法:

public class Person {
private final Date birthDate;

public Person(Date birthDate) {
// Defensive copy - see Item 39
this.birthDate = new Date(birthDate.getTime());
}

// Other fields, methods omitted

// DON'T DO THIS!
public boolean isBabyBoomer() {
// Unnecessary allocation of expensive object
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;
}
}

改进的写法:

class Person {
private final Date birthDate;

public Person(Date birthDate) {
// Defensive copy - see Item 39
this.birthDate = new Date(birthDate.getTime());
}

// Other fields, methods

/**
* The starting and ending dates of the baby boom.
*/
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方法的时候初始化这两个对象实际上意义不大(正如单例模式为什么懒加载的方法),但是作者并不推荐,这样会使方法变得更加复杂(这一点具体情况具体分析吧,也就是在性能的优化和复杂程度上如何做权衡了)。

3、文中讲的是适配器的形式。这一点没看懂,后面再仔细研究!

4、优先使用基本类型而不是装箱类型,要当心无意识的装箱。例如下面的一段代码,sum定以的类型是基本类型long的包装类Long,每加一次意味要实例化一次(和不提倡对String类型的字符串做反复的修改操作同样的道理,因为都是不可变类,必定造成堆空间的浪费),同时还有一次拆箱的操作。一次性能上是有一定的影响。因此尽量用基本类型。

public class Sum {
// Hideously slow program! Can you spot the object creation?
public static void main(String[] args) {
Long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i;
}
System.out.println(sum);
}
}

总结:适当情况下考虑对象的重用,避免创建不必要的对象,灵活运用,但不能一概而论!具体情况具体分析!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: