该章主题是什么时候有效的创建对象,以及适时的销毁对象和清理工作。
1.考虑用静态工厂方法代替构造函数
好处:
- 每次调用时,不用创建一个新的对象
- 可以返回一个原返回类型的子类型对象
工厂方式与抽象产品角色分离:class test1 implements test { @Override public void t() { // TODO Auto-generated method stub System.out.print("test1"); } } class test2 implements test { @Override public void t() { // TODO Auto-generated method stub System.out.print("test2"); } } interface test { public void t(); } public class factory1 { public static test getInstance(int i) { test t = null; if (i == 1) { t = new test1(); } else if(i == 2) { t = new test2(); } return t; } }
静态工厂和抽象产品角色结合:
class test1 extends factory2 {
}
class test2 extends factory2 {
}
public class factory2 {
public factory2() {
}
public static factory2 getInstance(int i) {
factory2 t = null;
if (i == 1) {
t = new test1();
} else if(i == 2) {
t = new test2();
} else {
t = new factory2();
}
return t;
}
}
坏处:
- 类如果没有Public的构造函数,则不能被子类化。(如工厂方式与抽象产品角色分离的写法)
- 与其他静态方法无区别,无法区别,除非通过方法名的命名习惯。
2.使用私有构造函数强化单例
- 提供一个final静态成员保存单例,并提供getInstance的公有静态工厂方法提供外面访问。
- 避免使用抽象类来强制该类不可实例化。
3.避免创建重复对象 ,特别是开销很大的对象
- 开销大的重复创建的时候,性能方面将远低于一次创建的处理。
- 通过维护自己的对象池来避免对象的创建不可取,除非都是重量级的。比如数据库连接池是正确使用的例子。
4.消除过期的对象引用
往往下面的程序是最容易忽略,易发生内存泄漏的,因为栈里面弹出来的对象不会被当作垃圾回收。
import java.util.EmptyStackException;
public class Stack {
private Object[] elements;
private int size = 0;
public Stack(int initialCapacity) {
this.elements = new Object[initialCapacity];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop(){
if(size == 0) {
throw new EmptyStackException();
}
// memory leak
return elements[--size];
}
private void ensureCapacity() {
if(elements.length == size) {
Object[] oldElement = elements;
elements = new Object[2 * elements.length + 1];
System.arraycopy(oldElement, 0, elements, 0, size);
}
}
}
内存泄漏的地方改为取出来后赋值null
import java.util.EmptyStackException;
public class Stack {
private Object[] elements;
private int size = 0;
public Stack(int initialCapacity) {
this.elements = new Object[initialCapacity];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop(){
if(size == 0) {
throw new EmptyStackException();
}
Object result = elements[--size];
elements[size] = null;
return result;
}
private void ensureCapacity() {
if(elements.length == size) {
Object[] oldElement = elements;
elements = new Object[2 * elements.length + 1];
System.arraycopy(oldElement, 0, elements, 0, size);
}
}
}