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

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

例如:

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);
	}
}

总结:适当情况下考虑对象的重用,避免创建不必要的对象,灵活运用,但不能一概而论!具体情况具体分析!

转载于:https://my.oschina.net/silence88/blog/827698

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值