Effective Java学习笔记--创建和销毁对象

创建和销毁对象

一.静态工厂方法代替构造器

 静态工厂方法的优缺点

  优点:

    1.可以自定义名称(可以将功能表述的更加清晰)

    2.不必每次调用都创建新的对象(同一对象重复使用)

    3.返回的类型可以是原返回类型的任何子类型对象

    4.简化创建对象时的代码

  缺点:

    1.如果不含有公开的构造器,就不能被子类化

    2.和普通的静态方法没有区别

二.遇到多个构造器参数时考虑用构建器

  如果我们现在需要编写一个描述客户信息的类,在客户的信息中名字是一定有的,其他的信息都是可能用,我们使用三种方法去完成:

1.重叠构造器方法(代码已经简化)

 1 /**
 2  * 客户信息
 3  */
 4 public class Customer {
 5     private  String name;//姓名
 6     private  String profession;//职业
 7     private  int age;//年龄
 8     private  String gender;//性别
 9     
10     public Customer(String name){
11         this.name=name;
12     }
13     
14     public Customer(String name,String profession){
15         this.name=name;
16         this.profession=profession;
17     }
18     
19     public Customer(String name,String profession,int age){
20         this.name=name;
21         this.profession=profession;
22         this.age=age;
23     }
24     
25     public Customer(String name,String profession,int age,String gender){
26         this.name=name;
27         this.profession=profession;
28         this.age=age;
29         this.gender=gender;
30     } 
31 }

  创建实例:

Customer customer=new Customer("李雷", "程序员", 27, "男");

  总结:这里是简化后的代码,此实例才4个参数就如此繁琐,随着参数的增加,将会失去控制。

2.JavaBean模式(调用无参构造方法,然后用set方法赋值)

 1 /**
 2  * 客户信息
 3  */
 4 public class customer {
 5     private  String name;//姓名
 6     private  String profession;//职业
 7     private  int age;//年龄
 8     private  String gender;//性别
 9     
10     public customer(){}
11     
12     public void setName(String name) {
13         this.name = name;
14     }
15     
16     public void setProfession(String profession) {
17         this.profession = profession;
18     }
19     
20     public void setAge(int age) {
21         this.age = age;
22     }
23     
24     public void setGender(String gender) {
25         this.gender = gender;
26     }
27 }

  创建实例:

        customer customer=new customer();
        customer.setAge(27);
        customer.setGender("男");
        customer.setName("李雷");
        customer.setProfession("程序员");

  总结:创建实例容易,也比较容易阅读,但是由于对象的构造过程被分到了几部调用中,JavaBean可能处于不一致的状态,而且使用此模式无法将类制作成不可变的。

3.构建器(Builder模式)

 1 /**
 2  * 客户信息
 3  */
 4 public class Customer {
 5     private final String name;//姓名
 6     private final String profession;//职业
 7     private final int age;//年龄
 8     private final String gender;//性别
 9     
10     public static class Builder{
11         private final String name;
12         
13         private String profession="无";
14         private int age=0;
15         private String gender="未知";
16         
17         public Builder(String name){
18             this.name=name;
19         }
20         
21         public Builder profession(String val){
22             profession=val;
23             return this;
24         }
25         
26         public Builder age(int val){
27             age=val;
28             return this;
29         }
30         
31         public Builder gender(String val){
32             gender=val;
33             return this;
34         }
35         
36         public Customer build(){
37             return new Customer(this);
38         }
39     }
40     
41     private Customer(Builder builder){
42         name=builder.name;
43         profession=builder.profession;
44         age=builder.age;
45         gender=builder.gender;
46     }        
47 }

  创建实例:

    创建对象时,类名后面加括号表示调用无参的构造函数;不加括号表示调用默认的构造函数或唯一的构造函数     
  Customer customer=new Customer.Builder("李雷").age(27).gender("男").profession("程序员").build();

  总结:编写容易,易于阅读,而且模拟了具名的可选参数,安全性高,后期的扩展性强。

3.单元素枚举是实现Singleton的最佳方法

1 public enum Elvis {
2     INSTANCE;
3     
4     public void leaveTheBuilding(){
5         System.out.println("Singleton!");
6     }
7 }

  创建实例:

        Elvis elvis=Elvis.INSTANCE;

4.消除对其对象的引用

  下面是一个栈的简单实现:

public class Stack {
    private Object[] elements;
    private int size=0;
    private static final int DEFAULE_INITAL_CAPACITY=16;
    
    public Stack(){
        elements=new Object[DEFAULE_INITAL_CAPACITY];
    }
    
    public void push(Object e){
        ensureCapacity();
        elements[size++]=e;
    }
    
    public Object pop(){
        if (size==0) {
            throw new EmptyStackException();
        }
        return elements[--size];
    }
    
    public void ensureCapacity(){
        if (elements.length==size) {
            elements=Arrays.copyOf(elements, 2*size+1);
        }
    }
}

  如果一个栈显示增长,然后再收缩,那么从栈中弹出的对象将不会被当做垃圾回收,我们应该将过期的引用清空,将pop方法改动如下:

    public Object pop(){
        if (size==0) {
            throw new EmptyStackException();
        }
        elements[size]=null;
        return elements[--size];
    }

 

  

posted @ 2017-02-22 09:57  亦梦亦醒  阅读(225)  评论(0编辑  收藏  举报