effective-java:创建和销毁对象

第一条:考虑使用静态工厂方法代替构造器
  • 静态工厂方法有名字,可以通过方法名字准确的了解想要创建的对象的详情,例如:输入的参数等。
  • 在静态方法里可以写逻辑,所以可能不必每次调用都会创建一个新的对象。
  • 不必返回此对象的实例,也可以根据自己的需要返回此对象的子类的实例。
  • 在创建参数化类型实例的时候,他们使代码变得根据简洁。
第二条:遇到多个构造器参数时要考虑用构建器

下面代码为构建器示例:

package createOrdestoryObject;

public class Clothes {

    private  String name = "";

    private  String color = "";

    private  int size = 0;

    private  double price = 0.00;

    public Clothes(Builder builder){
        this.name = builder.name;
        this.color = builder.color;
        this.size = builder.size;
        this.price = builder.price;
    }

    public static class Builder{

        private   String name = "";

        private   int size = 0;

        private  String color ;

        private  double price = 0.00;

        public Builder(String name ,int size){
            this.name = name;
            this.size = size;
        }

        public Builder Color(String color){
            this.color = color;
            return this;
        }

        public Builder Price(double price){
            this.price = price;
            return this;
        }

        public Clothes build(){
            return new Clothes(this);
        }
    }

    public static void main(String[] args) {
        //通过构建器得到Clothes实例
        Clothes clo = new Clothes.Builder("T恤", 32).Color("red").Price(99.99).build();
    }
}
第三条:用私有构造器或者枚举类型强化Singleton属性
package createOrdestoryObject;

public class Elvis {

    public static final Elvis INSTANCE = new Elvis();

    private Elvis(){}

    public static Elvis getInstance (){
        return INSTANCE;
    }
}
第四条:通过私有构造器强化不可实例化的能力

若企图将类变得不可实例化,可以是有私有构造器。参照上一个示例。

第五条:避免创建不必要的对象
public static void main(String[] args) {
        System.out.println(LocalTime.now());
        //错误的将long写为Long,这样会创建多个Long对象
        Long sum = 0L;
        for(long i =0 ;i<Integer.MAX_VALUE;i++){
            sum +=i;
        }
        System.out.println(sum);
        System.out.println(LocalTime.now());
    }

在这个例子中错误的使用Long这个对象,在我的机器上用Long计算用了22秒,而用long计算用了4秒,所以我们应尽量使用基本类型而不是装箱类型。

第六条:消除过期的对象引用

java的垃圾回收机制是利用根不可达来进行无用对象的回收的,若是一直有无用的引用引用着这个对象的话,这个对象是不会被垃圾回收器回收的。若是这样的无用对象越来越多的话,就会造成内存的泄露。

请看下面这个例子:

public class Stack {

    private Object [] elements;

    private int size = 0;

    private final static int DEFAULT_INITIAL_CAPACITY = 16;

    public Stack(){
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(Object e){
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop(){
        if(size == 0){
            throw new EmptyStackException();
        }
        Object obj = elements[--size];
        //此段代码必须有,否则数组中会一直保留着对这个对象的无效引用,直至该数组元素被覆盖。
        elements[size] = null;
        return obj;
    }

    public void ensureCapacity(){
        if(elements.length == size){
            elements = Arrays.copyOf(elements, 2*size+1);
        }
    }
}

注意elements[size] = null;此段代码必须有,否则数组中会一直保留着对这个对象的无效引用,直至该数组元素被覆盖。

第七条:避免使用终结方法

java中不仅不保证终结方法会被及时的执行,而且根本不保证它们会被执行,尽量使用显示的终结方法,如InputStream、OutputStream等类的close方法。