public class Stack {
private Object[] elements;
private int size=0;
public Stack(int initialsCapacity)
{
this.elements=new Object[initialsCapacity];
}
public void push(Object e)
{
ensureCapacity();
elements[size++]=e;
}
public Object pop() throws Exception
{
if(size==0)
{
throw new Exception();
}
return elements[size--];
}
private void ensureCapacity() {
// TODO Auto-generated method stub
if(elements.length==size)
{
Object[] oldElements=elements;
elements=new Object[elements.length*2+1];
System.arraycopy(oldElements,0,elements,0,size);
}
}
}
effective java上说有内存泄露,希望高人指点下,谢!!!
private Object[] elements;
private int size=0;
public Stack(int initialsCapacity)
{
this.elements=new Object[initialsCapacity];
}
public void push(Object e)
{
ensureCapacity();
elements[size++]=e;
}
public Object pop() throws Exception
{
if(size==0)
{
throw new Exception();
}
return elements[size--];
}
private void ensureCapacity() {
// TODO Auto-generated method stub
if(elements.length==size)
{
Object[] oldElements=elements;
elements=new Object[elements.length*2+1];
System.arraycopy(oldElements,0,elements,0,size);
}
}
}
effective java上说有内存泄露,希望高人指点下,谢!!!
举例:push 10个对象,然后pop8个,目前有效的就两个对象,但是pop之后,element数组中下标为2-9的8个对象引用还在,所以,这8个对象不会被gc释放
但是这个出栈操作,并没有真正的弹出Object,只是将Object返回了。
这个对象依然存在,因为elements对象数组依然持有那个弹出栈的对象的引用。
所以不会被回收。这样改下试试: public Object pop() throws Exception {
Object tmp;
if (size == 0) {
throw new Exception();
}
tmp = elements[size--];
elements[size] = null;
return tmp;
}
具体可以参照
java.util.Stack 的 pop() 方法。
private void ensureCapacity() {
if(elements.length==size) {
Object[] oldElements=elements;
elements=new Object[elements.length*2+1];
System.arraycopy(oldElements,0,elements,0,size);//System.arrayCopy 实现数组的深拷贝,并不是复制对象的引用,那么这里的oldElements你没有去释放它,每调用一次push就多余一些垃圾数据,这里除非换个实现,要么自己将oldElements释放
}
}
我的理解是:
根据构造函数的实现: elements=new Object[initialsCapacity];
elements指向了 new Object[initialsCapacity]那个数组对象。
在每次push对象的时候,调用ensureCapacity,判断是否长度已经超过了初始化(initialsCapacity)的容量。
如果超过了,
则用临时变量Object[]oldElements指向 原来的数组对象,
然后创建(elements.length*2+1)的数组,将其引用赋给了elements。
最后,通过System.arraycopy将原来的数组对象的数据拷贝到新创建的数组对象。
方法返回后,原来的数组的对象应该可以被回收了。
因为没有引用指向它了。
bzwm的观点是正确的,原先数组对象不再被引用,可以回收
public Object pop() throws Exception
{
if(size==0)
{
throw new Exception();
}
return elements[size--]; //这是问题的核心所在.
}
要求是的从"栈中移走元素",而不是仅仅返回它.因此:
要:
Object o=elements[size];
elements[size]=null; //这才是真正栈中移走它.
size--;
注:若程序中不是使用的数组来做栈,而是List之类,更是要注意是:移走 而不是仅仅 返回一个元素