第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.   
  3. import java.util.*;  
  4.   
  5. public class Person {  
  6.     private final Date birthDate;  
  7.   
  8.     public Person(Date birthDate) {  
  9.         // Defensive copy - see Item 39  
  10.         this.birthDate = new Date(birthDate.getTime());  
  11.     }  
  12.   
  13.     // Other fields, methods omitted  
  14.   
  15.     // DON'T DO THIS!  
  16.     public boolean isBabyBoomer() {  
  17.         // Unnecessary allocation of expensive object  
  18.         Calendar gmtCal =  
  19.             Calendar.getInstance(TimeZone.getTimeZone("GMT"));  
  20.         gmtCal.set(1946, Calendar.JANUARY, 1000);  
  21.         Date boomStart = gmtCal.getTime();  
  22.         gmtCal.set(1965, Calendar.JANUARY, 1000);  
  23.         Date boomEnd = gmtCal.getTime();  
  24.         return birthDate.compareTo(boomStart) >= 0 &&  
  25.                birthDate.compareTo(boomEnd)   <  0;  
  26.     }  
  27. }  

正确方式:
  1. // Doesn't creates unnecessary duplicate objects - page 21  
  2.   
  3. import java.util.*;  
  4.   
  5. class Person {  
  6.     private final Date birthDate;  
  7.   
  8.     public Person(Date birthDate) {  
  9.         // Defensive copy - see Item 39  
  10.         this.birthDate = new Date(birthDate.getTime());  
  11.     }  
  12.   
  13.     // Other fields, methods  
  14.   
  15.     /** 
  16.      * The starting and ending dates of the baby boom. 
  17.      */  
  18.     private static final Date BOOM_START;  
  19.     private static final Date BOOM_END;  
  20.   
  21.     static {  
  22.         Calendar gmtCal =  
  23.             Calendar.getInstance(TimeZone.getTimeZone("GMT"));  
  24.         gmtCal.set(1946, Calendar.JANUARY, 1000);  
  25.         BOOM_START = gmtCal.getTime();  
  26.         gmtCal.set(1965, Calendar.JANUARY, 1000);  
  27.         BOOM_END = gmtCal.getTime();  
  28.     }  
  29.   
  30.     public boolean isBabyBoomer() {  
  31.         return birthDate.compareTo(BOOM_START) >= 0 &&  
  32.                birthDate.compareTo(BOOM_END)   <  0;  
  33.     }  
  34. }  




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




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





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值