第5条 避免建立没必要要的对象

一般来讲,最好能重用对象而不是在每次须要的时候就建立一个相同功能的新对象。重用方式既快速、又流行。若是对象是不可变的(immutable),它始终能够被重用。java

首先举一个反面例子程序员

String result=new String("oschina");

该语句每执行一次就会建立一个String实例,若是这在一个循环中,将会有不少String实例被建立,有可能会建立成千上万的实例,显然这是没必要要的。上面的代码能够这样修改ide

String result="oschina";

这种写法只用了一个String实例,而不是每次都建立一个实例。 这样能够保证,对于全部在同一台虚拟机中运行的代码,只要它们包含相同的字符串字面常量,该对象就会被重用。性能

其次,对于同时提供了静态工厂方法和构造器的不可变类,一般能够使用静态工厂方法而不是构造器,以免建立没必要要的对象。例如,静态工厂方法Boolean.valueOf(String)几乎老是优先于构造器Boolean(String)。构造器在每次被调用的时候都会建立一个新的对象,而静态工厂方法则历来不要求这样作,实际上也不会这样作。this

除了重用不可变的对象以外,也能够重用那些已经不会被修改的可变对象。spa

反面例子code

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

这样的写法,isBabyBoomer方法每次被调用的时候,都会建立一个Calendar、TimeZone、Date实例,这显然是没必要要的。对象

对于上面的代码能够这样修改字符串

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

这样把每次须要调用的变量放到static静态块里面,这样就保证了避免频繁被调用的次数。从而使性能获得提升。
get

在Java 1.5 的发行版本中,有一种建立多余对象的新方法,称做自动装箱(autoboxing),它容许程序员将基本类型和装箱基本类型混用,按需自动装箱和拆箱。

public class Sum {
   // Hideously slow program! Can you spot the object creation?
   public static void main(String[] args) {
      LongTimes();
      longTimes();
   }

   public static void LongTimes(){
      long beginTime = System.currentTimeMillis();
      Long sum = 0L;
      for (long i = 0; i < Integer.MAX_VALUE; i++) {
         sum += i;
      }
      long endTime = System.currentTimeMillis();
      System.out.println("Long====总数:"+sum);
      System.out.println("Long====耗时:"+(endTime-beginTime)/1000);
   }


   public static void longTimes(){
      long beginTime = System.currentTimeMillis();
      long sum = 0L;
      for (long i = 0; i < Integer.MAX_VALUE; i++) {
         sum += i;
      }
      long endTime = System.currentTimeMillis();
      System.out.println("long====总数:"+sum);
      System.out.println("long====耗时:"+(endTime-beginTime)/1000);
   }

这种Long和long计算的结果以下,只由于将变量sum声明为Long而不是long,从而多计算了2*31次方,因此结论很明显,要优先使用基本类型而不是自动封装类型,要小心无心识的自动封装。

相关文章
相关标签/搜索