主要内容:如何创建对象;如何避免创建重复对象;如何保证对象能够适时地被销毁;
1.静态工厂方法代替构造函数并实现单例模式
package com.zgd;
class Single{
private String s;
private static final Single single = new Single();
private Single(){
s = "hello";
}
public static Single getInstance(){
return single;
}
}
public class Singleton {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Single s1 = Single.getInstance();
Single s2 = Single.getInstance();
System.out.println(s1==s2);//true
}
}
2.避免创建重复的对象
package com.zgd;
import java.util.Calendar;
class Person{
private Calendar birthday ;
public Person(Calendar birthday) {
super();
this.birthday = birthday;
}
//根据某个人的生日判断他是否是80后,这里的calendar1和calendar2每次都需要重新建立对象
public boolean isBetween(){
Calendar calendar1 =Calendar.getInstance();
calendar1.set(1979, 12, 31);
Calendar calendar2 =Calendar.getInstance();;
calendar2.set(1990, 1, 1);
return birthday.compareTo(calendar1) > 0 && birthday.compareTo(calendar2) < 0;
}
//为了不重复建立这些对象,我们建立两个常量
private static final Calendar calendar1;
private static final Calendar calendar2;
static{
calendar1 =Calendar.getInstance();
calendar1.set(1979, 12, 31);
calendar2 =Calendar.getInstance();;
calendar2.set(1990, 1, 1);
}
//根据某个人的生日判断他是否是80后,这里的calendar1和calendar2不需要每次都重建
public boolean isBetween2(){
return birthday.compareTo(calendar1) > 0 && birthday.compareTo(calendar2) < 0;
}
}
public class BirthdayCompare {
public static void main(String[] args) {
// TODO Auto-generated method stub
Calendar myDate =Calendar.getInstance();;
myDate.set(1983, 12, 31);
Person p = new Person(myDate);
System.out.println(p.isBetween());
System.out.println(p.isBetween2());
}
}
采用静态代码 static{}保证只被初始化一次
当然也可以通过延迟初始化到方法第一次调用的时候,但是这样会使实现非常复杂,除非是一些对象初始化需要很大的代价。比如,建立数据库的连接
3.消除过期的对象引用和避免使用中介函数finalize
java内存泄漏条件: JVM回收算法是很复杂的,我也不知道他们怎么实现的,但是我只知道他们要实现的就是:对于没有被引用的对象是可以回收的。所以你要造成内存泄露就要做到:持有对无用对象的引用!
Stack的例子
public class Stack {
private Object[] elements=new Object[10];
private int size = 0;
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){
Object[] oldElements = elements;
elements = new Object[2 * elements.length+1];
System.arraycopy(oldElements,0, elements, 0, size);
}
}
}
假如一个栈stack,开始push了10个对象,后来全部pop了。现在有用对象个数为0,但是由于elements始终占据了引用所以无法GC无法自动回收。
可以这样修改:
public Object pop(){
if( size == 0){
throw new EmptyStackException();
}
Object result = elements[--size]
rements[size] = null;
return result;
}
如何避免内存泄漏:消除过期对象的引用。
obj= null;
System.gc();//通知垃圾回收站进行回收,但是并不保证一定会回收。
尽量避免使用finalize函数,它和C++中的delete析构函数存在很大的不同!