创建和销毁对象

2017-06-03  本文已影响0人  凯诺婷

什么是静态工厂方法

返回一个类的实例的静态方法

优势

多个构造器解决方案

假如有2个必选参数和4个可选参数,那么构造函数至少要有5种,而且,每一次选择构造函数的时候还需要注意参数顺序,看api的时候还要点进去看
方案1:一个空的构造函数,其余参数用set方法来进行赋值,但这个有个不好的地方是,不能保证一个事务
方案2:builder模式,不直接生成对象,先生成一个builder对象,然后再将builder对象生成目标对象,具体例子如下:

public class NutritionFacts {
  private final int servingSize; //require
  private final int servings;   //require
  private final int calories;  //optional
  private final int fat;  //optional
  private final int sodium; //optional
  private final int carbohydrate; //optional
  public static class Builder {
    //对象的必选参数
    private final int servingSize;
    private final int servings;
    //对象的可选参数的缺省值初始化
    private int calories = 0;
    private int fat = 0;
    private int carbohydrate = 0;
    private int sodium = 0;
    //只用少数的必选参数作为构造器的函数参数
    public Builder(int servingSize,int servings) {
       this.servingSize = servingSize;
       this.servings = servings;
    }
    public Builder calories(int val) {
       calories = val;
       return this;
    }
    public Builder fat(int val) {
        fat = val;
        return this;
    }
    public Builder carbohydrate(int val) {
        carbohydrate = val;
        return this;
    }
    public Builder sodium(int val) {
        sodium = val;
        return this;
    }
    public NutritionFacts build() {
        return new NutritionFacts(this);
    }
 }
 private NutritionFacts(Builder builder) {
    servingSize = builder.servingSize;
    servings = builder.servings;
    calories = builder.calories;
    fat = builder.fat;
    sodium = builder.sodium;
    carbohydrate = builder.carbohydrate;
  }
}
//使用方式
public static void main(String[] args) {
   NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100)
   .sodium(35).carbohydrate(27).build();
   System.out.println(cocaCola);
}

单例模式

public class Elvis {
   public static final Elvis INSTANCE = new Elvis();
   private Elivs() { ... }
   public static Elvis getInstance() { 
      return INSTANCE; 
 }
   public void leaveTheBuilding() { ... }
}

避免创建不必要的对象

String s = new String("aaa");
String s = "aaa";

比较这两行代码,上面的语句每次执行的时候都会创建一个新的 String 实例,但是这些创建对象的动作全都是不必要的。而下面的语句只用了一个 String 实例,而不是每次执行的时候都创建一个新的实例。由于 String 被实现为不可变对象,JVM 底层将其实现为常量池,所有值等于"aaa"的对象实例共享同一对象地址,而且还可以保证,对于所有在同一 JVM 中运行的代码,只要他们包含相同的字符串字面常量,该对象就会被重用。
拓展:string、stringBuilder、stringBuffer的区别
String 字符串常量
(每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String)
StringBuffer 字符串变量(线程安全)对方法加了同步锁

public synchronized StringBuffer reverse() {
    super.reverse();
    return this;
}
public int indexOf(String str) {
    return indexOf(str, 0);        //存在 public synchronized int indexOf(String str, int fromIndex) 方法
}

*** synchronized的含义:
每一个类对象都对应一把锁,当某个线程A调用类对象O中的synchronized方法M时,必须获得对象O的锁才能够执行M方法,否则线程A阻塞。一旦线程A开始执行M方法,将独占对象O的锁。使得其它需要调用O对象的M方法的线程阻塞。只有线程A执行完毕,释放锁后。那些阻塞线程才有机会重新调用M方法。这就是解决线程同步问题的锁机制。 ***
StringBuilder 字符串变量(非线程安全)
总结
1.如果要操作少量的数据 <=> String
2.单线程操作字符串缓冲区 下操作大量数据 <=> StringBuilder
3.多线程操作字符串缓冲区 下操作大量数据 <=> StringBuffer

当一个类里面一些对象变量不会改变或者只需要初始化一遍时,可以进行如下操作,将变量初始化为final类型,并在static方法里面完成赋值,重用那些已知不会被修改的可变对象

public class Person {
   private static final Date BOOM_START;
   private static final Date BOOM_END;

   static {
      Calender c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
      c.set(1946,Calendar.JANUARY,1,0,0,0);
      BOOM_START = c.getTime();
      c.set(1965,Calendar.JANUARY,1,0,0,0);
      BOOM_END = c.getTime();
 }
   public boolean isBabyBoomer() {
      return birthDate.compareTo(BOOM_START) >= 0 && birthDate.compareTo(BOOM_END) < 0;
   }
}
上一篇 下一篇

猜你喜欢

热点阅读