第七条:消除过期的对象引用

消除过期的对象引用

java虽然有垃圾回收器,但是不是说在任何情况下都不用考虑内存泄露的问题了。
下面例子是一个简单的栈,包括入栈出栈。

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }
    //入栈
    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }
    //出栈
    public Object pop() {
        if (size == 0) throw new EmptyStackException();
        return elements[--size];
    }
    //确保栈数组容量
    public void ensureCapacity() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements,2*size+1);
        }
    }
}

这个栈方法里面看似没有任何问题,可以实现入栈出栈操作,但是仔细琢磨就会发现其中存在着内存泄露。
从程序中可以看出,一个栈如果先增长再收缩,从栈中弹出的对象即使不使用了,但是还是会有过期引用导致垃圾收集器不会回收他们,过期引用就是永远不会被回收的引用。
例如一个栈中现在有八个元素。栈的长度是16
先增长:往里面push了四个元素,现在成了12个。
再收缩:然后现在又pop了两个元素,现在成了10个元素。
对于程序来说,现在我们只需要栈中的10个元素就好了,其余的都应该被垃圾回收掉,但是刚才收缩pop了的两个元素,确还是有过期引用存在。即栈数组下边为10,11还是有对应的对象存在。这样子就导致了内存泄露。如果执行了一个递归入栈,没有及时清理过期引用,那么后果是不堪设想的。
想要避免这种情况发生,那么只需要清理过期引用就可以了,即栈中有一个元素被弹出,那么就清空引用就行了。
修改后的出栈如下所示。
这样子即使程序对过期的引用错误的使用了,也能及时的抛空指针异常,而不是错误的运行下去了。

    //出栈
    public Object pop() {
        if (size == 0) throw new EmptyStackException();
        Object element = elements[--size];
        //每弹出一个,就将栈该弹出下边的引用修改为null
        elements[size] = null;
        return element;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值