直接上例子:
如果自己实现了一个栈,pop
方法实现如下:
public Object pop(){
if(size==0)
throw new EmptyStackException();
return element[--size]; //短暂造成内存泄露
}
那么当前size对象虽然已经弹出了,但是element
仍然持有这个对象的引用,必须要等到push
操作覆盖这个引用GC
才可以工作。
再看看Java中的栈是怎么实现的
Stack.java
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
由于Java的Stack
直接继承了Vector
直接调用了Vector
的removeElementAt
方法,看下这个方法:
public synchronized void removeElementAt(int index) {
modCount++;
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - 1;
if (j > 0) {
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
看到最后一句显式设为null,注释都写好了,to let gc do its work。-,-
另外在《Practical Java》中把“不使用的对象应手动赋为null”作为一条推荐的编码规则,在周志明的《深入理解Java虚拟机》的Chapter8中也有说明。