Effective Jave 创建和销毁对象 5.避免创建不必要的对象

来源:互联网 发布:计算机二级c语言教材 编辑:程序博客网 时间:2024/05/22 14:00

一般来说,对于能够重用的对象,而不是在每次需要的时候就创建一个相同功能的新对象。重用的方式即快速,又流行。如果对象是不可变,他就始终可以被重用。

String s=new String("person");

该语句每次被执行时都会创建一个String实例,对于这些创建的动作完全是不必要的。传递给String构造器的参数,本身就是String实例,功能方面等同于构造器创建的所有对象。

改进后版本如下。

String s="person";

这个版本只用了一个String实例,而不是每次执行都会创建一个新的实例。对于所有在同一台虚拟机运行的代码,只要他们包含相同的字符串字面常量,就会被重用。

对于同时提供了静态工厂方法和构造器的不可变类,通常可以使用静态工厂方法而不是构造器,以避免创建不必要的对象。构造器每次在被调用时都会创建一个新的对象,而静态工厂方法则从来不要求这么做,实际上也不会这样做。

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


这个类建立了一个模型,用于检验一个人是否在1946到1964年出生
  
import java.util.*;  
  
public class Person {  
    private final Date birthDate;  
  
    public Person(Date birthDate) {  
      
        this.birthDate = new Date(birthDate.getTime());  
    }  
  
  
  
  
    public boolean isBabyBoomer() {  
      
        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实例。这是不必要的,下面的版本就是用静态域的初始化,避免效率这种效率低下的情况。


import java.util.*;  
  
class Person {  
    private final Date birthDate;  
  
    public Person(Date birthDate) {  
        this.birthDate = new Date(birthDate.getTime());  
    }  


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


改进后的person类,只在初始化时创建Calendar,TimeZone和Date实例一次,而不是在每次调用isBabyBoomer()的时候创建这些实例。如果频繁的调用isBabyBoomer(),那么性能将显著的提高。


在Java1.5发行版本中,有一种创建多余对象的新方法,称作自动装箱。
public class Sum {  
    public static void main(String[] args) {        
        Long sum = 0L;  
        for (long i = 0; i < Integer.MAX_VALUE; i++) {  
            sum += i;  
        }  
        System.out.println(sum);        
    }  

这段程序运行的答案是正确的,但比实际情况更慢一些,只因为打错了一个字符,一位这程序构造了大约2的31次方的Long实例,将sum的声明改成long,速度提升约7倍。


结论很明显,要优先使用基本类型。
阅读全文
1 0
原创粉丝点击