07.消除过期对象的引用

前言

《Effective Java》中文第三版,是一本关于Java基础的书,这本书不止一次有人推荐我看。其中包括我很喜欢的博客园博主五月的仓颉,他曾在自己的博文《给Java程序猿们推荐一些值得一看的好书》中也推荐过。加深自己的记忆,同时向优秀的人看齐,决定在看完每一章之后,都写一篇随笔。如果有写的不对的地方、表述的不清楚的地方、或者其他建议,希望您能够留言指正,谢谢。

《Effective Java》中文第三版在线阅读链接

是什么

过期对象的引用:指的是永远不会再被解除的引用。为什么会出现这样的情况,这是因为我们的栈在显示增长,然后再收缩,那么从栈中弹出来的对象将不会被当做垃圾回收,即使使用的栈的程序不再引用这些对象,它们也不会被回收。因为,栈内部维护着对这些对象的过期引用。

没有消除过期对象实例,代码如下:

/**
 * @author gongguowei01@gmail.com
 * @since 2020-01-19
 */
public class Stack {

    public Object[] elements;

    public int size = 0;

    private static final int DEFAULT_VALUE = 16;

    public Stack() {
        elements = new Object[DEFAULT_VALUE];
    }

    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop() {
        if (0 == size) {
            throw new EmptyStackException();
        }
        return elements[--size];
    }

    public void ensureCapacity() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }
}

上方代码测试实例如下

/**
 * @author gongguowei01@gmail.com
 * @since 2020-01-19
 */
public class Test {
    public static void main(String[] args) {
        Stack stack = new Stack();

        stack.push("1");

        stack.push("2");

        stack.pop();

        stack.push("3");
    }

}

运行结果如下
在这里插入图片描述
当我们调用pop()方法时,size变为1,但是elements数组中还存在过期对象“1”的引用。

消除过期对象的引用,代码实例如下

/**
 * @author gongguowei01@gmail.com
 * @since 2020-01-19
 */
public class Stack02 {
    public Object[] elements;

    public int size = 0;

    private static final int DEFAULT_VALUE = 16;

    public Stack02() {
        elements = new Object[DEFAULT_VALUE];
    }

    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop() {
        if (0 == size) {
            throw new EmptyStackException();
        }
        Object result = elements[--size];
        //消除过期对象引用
        elements[size] = null;
        return result;
    }

    public void ensureCapacity() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }
}

哪里用

在有可能出现内存泄露的场景

  • 缓存
  • 自己管理内存的场景
  • 监听器和其他回调

总结

不消除过期对象的引用,将会引起内存泄露,内存泄漏通常不会表现为明显的故障,所以它们可能会在系统中保持多年。 通常仅在仔细的代码检查或借助堆分析器(heap profiler)的调试工具才会被发现。 因此,学习如何预见这些问题,并防止这些问题发生,是非常值得的。

posted @ 2020-01-19 22:26  龚国玮  阅读(150)  评论(0编辑  收藏  举报