消除过期的对象引用
书中的例子如下:问题出在pop方法上,pop出去以后,stack的size本身减少1,size–,外部会持有该对象的引用,但是即便外部释放掉该element的引用,stack本身还有一个“保护机制”,栈内部会维护着这个对象的过期引用。
为什么呢?
这个是数组的特性,好比创建了一个16大小的数组,调用pop方法相当于这时候对第16个数组对象创建一个外部引用,这个对象本身还是在内存中有空间的。换而言之,这个第16个对象此时此刻即被外部调用的一个引用持有,也同时被stack本身的数组持有,也许有人认为–size了,现在应该变为15大小的数组了,为什么还持有第16个呢?
这里首先要理解数组对象创建的时候内存的变化。声明数组过程中,变量保存在栈中,创建并进行初始化时,数组元素是保存在堆中,数组通过引用指针指向数组元素。
对于基本类型数组的初始化,程序直接先为数组分配内存空间,再将数组元素的值存入对应的内存里。
对于引用类型数组的数组元素依然是引用类型,因此数组元素里存储的还是引用,它指向另一块内存,该内在里存储了该引用变量所引用的对象。
这里的size其实只是栈中一个域变量的变化,而非真正数组的变化,原来作为基本类型的引用依然存在于第16个数组的位置上。
1 | public class Stack { |
术语:过期引用(obsolete reference) ,指永远不会被解除的引用。
书中也给了修改得方式如下:1
2
3
4
5
6
7
8public Object pop(){
if(size == 0){
throw new EmptyStackException();
}
Object result = elements[--size];
elements[size] = null;
return result;
}