避免创建不必要的对象

Java中Sting很特别,有如下两种初始化方式:

(1).String s1 = “This isstring1”;

(2).String s2 = new String(“Thisis string2”);

第一种字符串初始化方式,当有多于一个字符串的内容相同情况,字符串内容会放在字符串缓冲池中,即字符串内容在内存中只有一份。

第二种字符串初始化方式,不论有没有字符串值相同,每次都会在内存堆中存储字符串的值。

如果一个方法中字符串的值都相同,调用100万次情况下第一种字符串初始化方式的内存占用率很低,性能非常高,而第二种方式的字符串初始化则会占用大量的内存.

看下面一个例子,直观感受创建不必要对象的性能危害:

 

[java]  view plain  copy
 
  1. public class Person{  
  2.     private Date birthDate;  
  3.     //判断是否是婴儿潮出生的人  
  4.     public boolean isBabyBoomer(){  
  5.     Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(“GMT”));  
  6.     //婴儿潮开始时间  
  7.     cal.set(1946, Calendar.JANUARY, 1000);  
  8. Date boomStart = cal.getTime();  
  9. //婴儿潮结束时间  
  10.     cal.set(1965, Calendar.JANUARY, 1000);  
  11. Date boomEnd = cal.getTime();  
  12. return birthDate.compareTo(boomStart) >= 0 && birthDate.compareTo(boomEnd) < 0;  
  13. }  
  14. }  

 

每次调用isBabyBoomer()方式时,都需要创建Calendar,TimeZone,boomStart和boomEnd四个对象,测试调用该方法1000万次,大约耗时32秒。

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

 

[java]  view plain  copy
 
  1. public class Person{  
  2.     private Date birthDate;  
  3.     private static final Date BOOM_START;  
  4.     private static final Date BOOM_END;  
  5.     static{  
  6.     Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(“GMT”));  
  7.     //婴儿潮开始时间  
  8.     cal.set(1946, Calendar.JANUARY, 1000);  
  9. BOOM_START = cal.getTime();  
  10. //婴儿潮结束时间  
  11.     cal.set(1965, Calendar.JANUARY, 1000);  
  12. BOOM_END = cal.getTime();  
  13. }  
  14.     //判断是否是婴儿潮出生的人  
  15.     public boolean isBabyBoomer(){  
  16. return birthDate.compareTo(BOOM_START) >= 0 && birthDate.compareTo(BOOM_END) < 0;  
  17. }  
  18. }  

 

经测试,调用1000万次,耗时大约130毫秒,性能提高250倍。

再看第二个例子,计算所有的int之和,代码如下:

 

[java]  view plain  copy
 
  1. public CalculateInt{  
  2.     public static void main(String[] args){  
  3.     Long sum = 0L;  
  4.     for(long i = 0; i < Integer.MAX_VALUE; i++){  
  5.     sum += i;  
  6. }  
  7. System.out.println(sum);  
  8. }  
  9. }  

 

由于sum是Long类型,而不是原始类型的long,因此总共进行了2的31次方不必要的类型自动封装(将原始类型的long封装为Long),总共耗时大约43秒。

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

猜你喜欢

转载自windpoplar.iteye.com/blog/2315910