For example:程序员
public static Boolean valueOf(boolean b){ return b ? Boolean.TRUE : Boolean.FALSE; }
优点:缓存
缺点:安全
对于多个参数的构造器或者静态方法,通常习惯采用重叠构造器(telescoping constructor)模式app
//Telescoping constructor pattern public class PizzaIngredients{ private final int salt; //optional private final int chess; //o private final int sausage; //o private final int flour; // required private final int water; //r ... public PizzaIngredients(int flour, int water){ this(flour, water, 0); } public PizzaIngredients(int flour, int water, int salt){ this(flour, water, salt, 0); } public PizzaIngredients(int flour, int water, int salt, int chess){ this(flour, water, salt, chess, 0); } public PizzaIngredients(int flour, int water, int salt, int chess, int sausage){ this.flour = flour; this.water= water; this.salt= salt; this.chess= chess; this.sausage= sausage; } }
若是构造参数太多这种方式代码也会变得很难编写,且不易阅读。性能
第二种方式是采用JavaBeans模式,即设置每一个参数的默认值,并给每一个field加上setter方法,要设置某个值时直接调用其对应的setter方法。可是JavaBean在构造过程当中可能会处于不一致状态,而且JavaBeans模式阻止了把类作成不可变的可能,这就须要付出额外的努力来确保它的线程安全。ui
第三种替代方法是Builder模式。客户端利用必要的参数获得一个builder对象,在builder对象上调用相似setter的方法,来设置每一个相关的可选参数,最后调用无参的build方法来生成不可变对象。this
public class PizzaIngredients{ private final int salt; //optional private final int chess; //o private final int sausage; //o private final int flour; // required private final int water; //r ... public static class Builder{ // required parameters private final int flour; private final int water; // optional private int salt = 0; private int chess = 0; private int sausage = 0; public Builder(int flour, int water){ this.flour = flour; this.water= water; } public Builder salt(int val){ salt = val; return this; } public Builder chess(int val){ chess = val; return this; } public Builder sausage (int val){ sausage = val; return this; } public PizzaIngredients build(){ return new PizzaIngredients (this) }
}
private PizzaIngredients(Builder builder){
flour = builder.flour;
water = builder.water;
salt = builder.salt;
chess = builder.chess;
sausage = builder.sausage;
}
}
// 客户端代码
PizzaIngredients pizza = new PizzaIngredients.Builder(200, 150).salt(5).chess(20).sausage(25).build();
Builder模式优点在于参数可变,并且不须要考虑顺序。可是Builder模式比重叠构造器模式更加冗长,最好在很对参数是使用。spa
三种方式实现Singleton:线程
1. 公有静态成员是final域code
//Singleton with public final field public class Wills{ public static final Wills INSTANCE = new Wills(); private Wills(){ }; ... }
2. 公有成员是静态工厂方法
//Singleton with static factory public class Wills{ private static final Wills INSTANCE = new Wills(); private Wills(){ }; public static Wills getInstance(){ return INSTANCE; } ... }
这两种方式在存在借助AccessibleObject.setAccessible方法,经过方式机制调用私有方法的可能。为抵御这种攻击,能够修改构造器,在实例被第二次建立时抛出异常。
而且每次反序列化一个序列化的实例时,都会建立一个新的实例,这须要声明全部实例域都是transient,并提供一个readResolve方法。
3. 单元素枚举类型
// Enum singleton - the preferred approach public enum Wills{ INSTANCE; ... }
这种方法在功能上相似公有域方法,但它更加简洁并且无偿的提供了序列化机制,绝对防止屡次实例化。单元素枚举类型已经成为实现Singleton的最佳方法。
不须要被实例化的类,能够经过私有构造器使其不能被实例化。
Public class UtilityClass { private UtilityClass(){ throw new AssertionError(); } }
除了不可变的对象,也能够重用已知不会修改的对象。
可使用静态初始化器(initializer)来初始化代码块。
Public class Person{ private final static String name; private final static String gender; static { Calendar cal = Calendar.getInstance(Timezone.getTimeZone("GMT")); ... ... }
public class Stack { private Object[] elements; private int size = 0; private static final 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(); return elements[--size]; } private void ensureCapacity() { if(elements.length == size){ elements = Arrays.copyOf(elements, 2 * DEFAULT_INITIAL_CAPACITY + 1); } } }
这段代码中并无明显的错误,可是这个程序中隐藏了一个问题,有一个“内存泄漏”,随着垃圾回回收器活动的增长,或者因为内存占用的不断增长,程序性能的下降会逐渐表现出来。
若是一个栈先是增加,而后再收缩,那么从栈中弹出来的对象将不会被当作垃圾回收,即便使用栈的程序再也不引用这些对象,他们也不会被回收。这是由于,栈内部维护着对这些引用的过时引用(obsolete reference)。所谓过时引用,是指永远也不会再被解除的引用。修复这类问题的方法很简单,一旦对象引用已通过期,只需清空这些引用便可。对于本例,以下修改:
public Object pop(){ if(size == 0) throw new EmptyStackException(); Object result = elements[--size]; elements[size] = null; return result; }
清空对象引用应该是一种例外,而不是一种规范行为。
通常而言,只要是本身管理内存,程序员就应该警戒内存泄漏问题。
内存泄漏的另外一个常见来源是缓存。
内存泄漏的第三个常见来源是监听器和其余回调。