import java.util.EmptyStackException;

public class Stack {
    //有了垃圾回收功能,我们就不需要考虑内存管理了吗?? NO!!
    /**
     *何时需要手工清空引用??
     *.一旦一个类自己管理它的内存,我们就应该警惕内存泄露的问题了。
     *   一旦一个元素被释放掉,该元素中包含的所有对象引用都要被清除
     *2.缓存,因为放在缓存中的对象引用很容易被遗忘,以至于它不再被用之后的很长一段时间内仍然留在缓存中。
     *    一个方法是用WeakHashMap代替缓存,另外一个方法需要java.util.TimerAPI来完成
     */
    private Object[] elements;
    privateintsize=0;
    public Stack(int initialCapacity){
       this.elements = new Object[initialCapacity];
    }
    publicvoid push(Object obj){
       ensureCapacity();
       elements[size++] = obj;
    }
    public Object pop(){
       if (size== 0)
           thrownew EmptyStackException();
       /**
        *注意:不严格的讲,下面这条语句可能会导致"内存泄露"
        *因为如果一个栈先是增长,然后再收缩,那么栈中弹出来的对象将不会被当作垃圾回收(即使使用
        *栈的客户程序不再引用这些对象),因为栈内部维护着这些对象的过期引用(obsoletereference
        *,是指永远也不会被解除的引用),本例而言,elements数组的活动区域(activeportion,
        *指下标小于size的那部分)之外的引用都是过期的
        */
       //return elements[--size];
       /**
        *修改如下
        *清空过期引用的另一个好处是,如果它们以后又被错误地解除引用,程序就会马上抛出
        *NullPointerException异常,而不是悄悄地错误运行
        */ 
       Object result = elements[--size];
       elements[size]=null;
       return result;
    }
    //ensure space for at least one more element,roughly doubling the 
    //capacity each time the array needs to grow
    privatevoid ensureCapacity(){
       if(elements.length == size){
           Object[] oldElements = elements;
           elements = new Object[2* elements.length+1];
           System.arraycopy(oldElements, 0, elements, 0, size);
       }
    }
     publicstaticvoid main(String[] args) { 
            Stack s = new Stack(0);
            for (int i=0; i<100; i++)
                s.push(i);
            for (int i=0; i<100; i++)
                System.out.println(s.pop());
        }
}

posted on 2008-04-22 18:49  wxf0701  阅读(333)  评论(0编辑  收藏  举报