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

重用不可变对象

一般来说, 最好能重用对象, 而不是在每次需要的时候创建一个相同功能的新对象.
重用:快速,流行
新建:慢,浪费存储.

反向示例

String str = new String("stringette"); //DON'T DO THIS

"stringette" 本身就是String实例.

正向示例:

String str = "stringette";

选择静态工厂方法而不是构造器

当一个不可变类同时提供静态工厂方法和构造器时,通常可以选择静态工厂方法而不是构造器,以避免创建不必要的对象.

  • 构造器: 一般是创建一个新的对象, Boolean(String)
  • 静态工厂方法:一般是返回已有对象,例如 Boolean.valueOf(Stirng)

重用已知不会被修改的可变对象\

不要这么做:

public class Person {
    private final Date birthDate;
    ...
   
    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;

** 应该这么做:**

public class Person() {
    private final Date birthDate;
    ...
    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;
    }
}

优先使用基本类型,而不是装箱基本类型, 要当心无意识的自动装箱

Java 1.5版本中, 实现自动装箱(autoboxing),允许将基本类型和装箱基本类型混用.,按需自动装箱和拆箱.

不要这么做:

// Slow program. Where is the object creation?
public static void main(String[] args) {
    Long sum = 0L;
    for (long i = 0; i < Integer.MAX_VALUE; i++) {
        sum += i;
    }

    System.out.println(sum);
}

sum的声明是Long,而不是 long, 这样意味着程序构造了大约2^31个多余的Long实例.

  • Effective Java 第5条:当你应该重用现有对象的时候,请不要创建新的对象.(代码风格和性能)
  • Effective Java 第39条(defensive copying保护性拷贝): 当你应该创建新的对象的时候,请不要重用现有的对象.(潜在的错误和安全漏洞)

考虑点: 使用重用对象要付出的代价 VS 创建重复对象的代价
例如遍历列表的同时处理列表中的元素,这时重用现有对象可能会导致代码错误. 而创建重复对象的代价仅仅是影响程序的风格和性能.

你可能感兴趣的:(Effective Java 第5条: 避免创建不必要的对象)