1 考虑用静态方法代替构造器
1). 静态方法优点:
- 有名称,更容易使用和理解。而一个累只有一个带有指定签名的构造器,当需要多个构造器时,各构造器参数个数、类型及类型顺序上可能有所不同,这样不易于区分。
- 不必在每次调用它们的时候都创建一个新对像,可以为重复调用返回相同对象。
- 可以返回原返回类型的任何子类型的对象,API可以返回对象,同时又不会使对象变成公有的。(理解服务提供者框架的应用)
- 在创建参数化类型实例的时候,使得代码变得更加简洁。使用构造器即使参数再明显也得指定。
Map <String,List<String>> m=new HashMap <String,List<String>>
使用静态工程方法的替代方案:
Map <String,List<String>> m=HashMap.newInstance()
2)缺点
- 如果类不含共有的或者受保护的构造器,就不能被子类化。(子类实例化时需要调用父类构造器)
- 它们与其它静态方法没有任何区别,在导出的API中没有被区分
2 遇到多个构造器参数时要考虑构造器
当一个类有大量的可选参数时,该如何实例化该类?
采用重叠构造器模式
这种方法在参数较多时,需要许多构造器,造成客户端代码很难编写和阅读。参数顺序改变时,编译器不一定报错。采用javaBean模式
先调用一个无参构造器,在使用setter方法设置参数。在构造过程中JavaBean可能处于不一致状态,并且阻止了把类做成不可变的可能使用Builder模式
示例如下:
//builder pattern
public class NutritionFacts{
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
// Required parameters
private final int servingSize;
private final int servings;
// Optional parameters - initialized to default values
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();
}
}
3 用私有构造器或者枚举类型强化Singleton属性
Singleton指仅仅被实例化一次的类,实现Singleton有两种方法
- 使用公有静态final域
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() {
}
public void leaveTheBuilding() {
System.out.println("Whoa baby, I'm outta here!");
}
// This code would normally appear outside the class!
public static void main(String[] args) {
Elvis elvis = Elvis.INSTANCE;
elvis.leaveTheBuilding();
}
}
使用公有静态工厂方法
public class Elvis {
private static final Elvis INSTANCE = new Elvis();private Elvis() {
}
public static Elvis getInstance() {
return INSTANCE;
}
public void leaveTheBuilding() {
System.out.println("Whoa baby, I'm outta here!");
}
// This code would normally appear outside the class!
public static void main(String[] args) {
Elvis elvis = Elvis.getInstance();
elvis.leaveTheBuilding();
}
}
静态工厂方法比较灵活,在不改变API的前提下,可以改变该类是否应该为Singleton的想法。不管使用以上那种方法构造器必须保持为私有的
- 包含单个元素的枚举类型
4 通过私有构造器强化不可实例化的能力
当有些类只包含静态方法和静态域,这样的类是没有必要实例化的。为了防止该类被实例化,可以为其添加私有构造器(如果不添加私有构造器,则默认会使用缺省的公有构造器)。
5 避免创建不必要的对象
一般来说,最好能重用对象而不是每次需要的时候就创建一个相同功能的新对象。重用方式既快速又流行。
不可变对象始终可以被重用;那些已知不会被修改的可变对象也可重用。
延迟初始化:在对象被第一次调用的时候进行初始化,以避免有些对象初始化后,一直不被调用。
自动装箱会创建出多余的对象,应优先使用基本类型而不是装箱基本类型。
通过使用静态工厂方法而不是构造器,以避免创建不必要的对象。
重用对象不只是因为创建对象代价昂贵,它可以提升程序的清晰性、简洁性和功能性。
6 消除过期的对象引用
有些对象在不被引用后,Java虚拟机是不会把其当作垃圾进行回收,此时需要人工销毁,否则容引起内存泄露。
如果一个栈先增长,再收缩,则弹出的对象将不会被当作垃圾回收
当一个对象从栈中被弹出时,则需要清空该对象的引用。内存泄露另一个常见来源是缓存
缓存应该时不时的清除掉没有用的项,这项清除工作可以由一个后台线程来完成,或者也可以在给缓存添加新条目的时候顺便清理。内存泄露第三个常见来源是监听器和其他回调
7 避免使用终结方法
终结方法通常是不可预测的,终结方法线程的优先级比其他线程优先级要低的多,不能保证会被及时执行,还会严重影响性能。
可以使用终止方法替代终结方法(比如InputStream类的close方法),其通常与try-finally结构结合起来使用。
- 终结方法通常有两种用途:作为安全网,在终止方法没有被执行时,调用以释放资源。本地对等体不能被垃圾回收器发现,因此在需要回收该对象时,如果该对象不拥有关键资源,可以使用终结方法,否则使用终止方法。