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

一般来说,最好能重用对象而不是在每次需要的时候就创建一个相同功能的新对象。


demo1:
String s = new String("hello world");
需要改成
String s = "hello world";
因为第一种写法,每一次调用的时候都会创建一个新的String实例。但是第二种写法,在同一台虚拟机中运行的代码,只要他们包含相同的字符串字面常量,就会被重用。


对于同时提供了静态工厂方法(见第1条)和构造器的不可变类,通常可以使用静态工厂方法而不是构造器,以避免创建不必要的对象。




除了重用不可变的对象之外,也可以重用那些已经不会被修改的可变对象。
错误方式:
isBabyBoomer每次被调用,都会新建一个Calendar、一个TimeZone和两个Date实例。
  1. // Creates lots of unnecessary duplicate objects - page 20-21
  2. importjava.util.*;
  3. publicclassPerson {
  4. privatefinalDate birthDate;
  5. publicPerson(Date birthDate) {
  6. // Defensive copy - see Item 39
  7. this.birthDate =newDate(birthDate.getTime());
  8. }
  9. // Other fields, methods omitted
  10. // DON'T DO THIS!
  11. publicbooleanisBabyBoomer() {
  12. // Unnecessary allocation of expensive object
  13. Calendar gmtCal =
  14. Calendar.getInstance(TimeZone.getTimeZone("GMT"));
  15. gmtCal.set(1946, Calendar.JANUARY,1,0,0,0);
  16. Date boomStart = gmtCal.getTime();
  17. gmtCal.set(1965, Calendar.JANUARY,1,0,0,0);
  18. Date boomEnd = gmtCal.getTime();
  19. returnbirthDate.compareTo(boomStart) >=0&&
  20. birthDate.compareTo(boomEnd) <0;
  21. }
  22. }

正确方式:
  1. // Doesn't creates unnecessary duplicate objects - page 21
  2. importjava.util.*;
  3. classPerson {
  4. privatefinalDate birthDate;
  5. publicPerson(Date birthDate) {
  6. // Defensive copy - see Item 39
  7. this.birthDate =newDate(birthDate.getTime());
  8. }
  9. // Other fields, methods
  10. /**
  11. * The starting and ending dates of the baby boom.
  12. */
  13. privatestaticfinalDate BOOM_START;
  14. privatestaticfinalDate BOOM_END;
  15. static{
  16. Calendar gmtCal =
  17. Calendar.getInstance(TimeZone.getTimeZone("GMT"));
  18. gmtCal.set(1946, Calendar.JANUARY,1,0,0,0);
  19. BOOM_START = gmtCal.getTime();
  20. gmtCal.set(1965, Calendar.JANUARY,1,0,0,0);
  21. BOOM_END = gmtCal.getTime();
  22. }
  23. publicbooleanisBabyBoomer() {
  24. returnbirthDate.compareTo(BOOM_START) >=0&&
  25. birthDate.compareTo(BOOM_END) <0;
  26. }
  27. }




Map接口的keySet方法返回该Map对象的Set视图,每次调用keySet都返回同样的Set实例。当其中一个返回对象发生变化时,所以其他的返回对象也要发生 变化。




自动装箱(autoboxing):
将sum的生命从Long改为long,运行速度提成了7倍。
demo:
  1. publicclassSum {
  2. // Hideously slow program! Can you spot the object creation?
  3. publicstaticvoidmain(String[] args) {
  4. longbeginTime = System.currentTimeMillis();
  5. System.out.println(beginTime);
  6. Long sum = 0L;
  7. for(longi =0; i < Integer.MAX_VALUE; i++) {
  8. sum += i;
  9. }
  10. System.out.println(sum);
  11. longendTime = System.currentTimeMillis();
  12. System.out.println(endTime);
  13. System.out.println((endTime-beginTime)/1000);
  14. }
  15. }





(但是,有些场景重用对象,比创建新对象付出的代价要高很多--详细见第39条:保护性拷贝defensive copying)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值