一 创建和销毁对象
1.使用静态工厂方法替代构造器
这里的静态工厂并不是设计模式中的静态工厂,它就是用一个静态方法来替代构造器产生类的实例。
优点:
1.由于是方法,所以有名称,如果有良好的命名就可以通过名字判断该方法到底返回的时什么实例,可以区分重载的构造器。
2.可以不必每次调用的时候都创建一个新的对象,比如单例模式
3.可以返回原返回类型的任意子类型的对象,比构造器更加灵活
缺点:
1.由于是一个静态方法,如果没有帮助文档,客户端往往不容易发现它可以创建一个对象
2.如果类的构造器私有化了,那么静态工厂方法也不能实现子类化(返回类的子类)
2.遇到多个构造器参数时考虑使用构建器(Builder)
在碰到构造器中有多个参数时,我们可以考虑使用下面三种方法:
1.构造器的重载:如果参数过多,会造成构造器难以编写和阅读
2.使用setter方法进行设置参数:虽然解决了构造器重载的问题,但是因为类变成了有状态的类,所以好需要考虑在多线程环境下 安全的问题,而且如果类的实例要求是不可变类,用setter方法显然无
3.使用builder构建器:
public class Person {
private int id;
private int age;
private final int height;
private final int width;
private final int weight;
//静态内部类
public static class Builder{
private final int id;
private final int age;
private int height = 0;
private int width = 0;
private int weight = 0;
public Builder(int id,int age){
this.id = id;
this.age = age;
}
public Builder height(int height){
this.height = height;
return this;
}
public Builder width(int width){
this.width = width;
return this;
}
public Builder weight(int weight){
this.weight = weight;
return this;
}
public Person build(){
return new Person(this);
}
}
//私有构造器,只供内部类使用,对实例初始化
private Person(Builder builder){
this.id = builder.id;
this.age = builder.age;
this.height = builder.height;
this.width = builder.width;
this.weight = builder.weight;
}
}
获得对象:
Person person = new Person.Builder(1, 28).height(184).weight(80).width(90).build();
使用构建器这种方式创建对象既保证了像构造器模式的安全性也保证了setter模式的可读性
3.使用枚举增强单例模式
详见《Java设计模式之单例模式》
4.通过私有构造器强化不可实例化的能力
有一些类中全部是静态方法,比如Math和Arrays,如果不希望被创建实例或者子类,那么可以用private修饰构造器,如果也不希望类的内部使用,可以在构造器中抛出异常,并注释给予提示
5.避免创建不必要的对象
当应该重用对象的时候就不要创建新的对象,当需要创建新的对象的时候就不要重用对象。
尽量使用基本类型而不是包装类型,避免无意识的自动装箱。
6.消除对象的过期引用
内存泄漏有三个常见的来源:
1)对象的过期引用:即一个对象外部访问不到,但是他依然持有引用,这时可以通过设置为null让虚拟机回收
2)缓存:如果缓存中的没有被外界所引用,那么它的存在没有意义也不会被垃圾回收,这时可以使用WeakHashMap(当除了自身对key有引用外,此key没有被其它引用,那么将被垃圾回收)
3)注册监听和回调:如果实现了一个API,客户端注册回调,却没有显示的调用取消注册,那么它们就会被堆积。同样可以使用WeakHashMap
7.避免使用finalize方法
由于Java虚拟机有垃圾回收机制,所以Java程序员无需像C/C++程序员自己进行垃圾回收。Java虽然提供了finalize()方法可以用于垃圾回收,但是并不能保它被及时的调用。