我们有代码:
Iterator<Object> it = new Collection<Object>(){/*...implementation...*/}.iterator();
问:垃圾收集器会删除我创建的对象以表示集合吗?在形式上,我们没有引用此对象,但it (Iterator <Object>)
仍然与匿名类对象的内部相关联。
换句话说,请考虑代码:
Iterator<Object> it = new Collection<Object>(){ // String (1)
private Object[] array;
public Iterator<Object> iterator(){
/*Here, an iterator that references this.array is returned
+ Performing its tasks*/
}
/* + other implementation...*/
}.iterator();
然后GC会删除第一行中创建的对象,我们客观地没有链接到? //String (1)
对于那些特别喜欢编写伪答案的人来说,这里是我的迭代器看起来像的代码:
Iterator<Object> it = new Collection<Object>() { // String (1)
private Object[] array2;
@Override
public Iterator<Object> iterator() {
return new Iterator<Object>() {
Object[] array;
{
array = array2;
}
@Override
public boolean hasNext() {
// We do what is necessary
return false;
}
@Override
public Object next() {
// We do what is necessary
return null;
}
};
}
/* + other implementation... */
}.iterator();
小额外问:
我可以将“array2”(在Collection的实现中)重命名为“array”吗?那么如何在Iterator的实现中使用它?
return new Iterator<Object>() {
Object[] array;
{
array = array2; // array = array ? It doesn't work. How refer to array above
}
// and so on...
关于重复......不是this question。也许它看起来像,但我希望得到关于DELETING的问题的答案。这会发生或不发生,为什么? +接收其他问题的答案很重要。 That question可以帮助某人了解我的问题的答案,但不是我。
答案 0 :(得分:0)
如果赋予外部类相同的名称array
,则无法访问外部类'字段,只要外部类是匿名内部类。但是,第二个array
字段的整个维护已经过时,因为它不会阻止内部(大多数)类维护对其外部实例的引用,如Do anonymous classes always maintain a reference to their enclosing instance?中所述。
这两个问题的解决方案是相同的,不要使用匿名内部类,而是使用命名的嵌套类,或者将其移动到不具有范围外部实例的工厂方法中:
Iterator<Object> it = new AbstractCollection<Object>() {
private Object[] array;
@Override
public Iterator<Object> iterator() {
return getIterator(array);
}
@Override
public int size() {
throw new AssertionError("no-one's gonna call this here");
}
}.iterator();
…
static Iterator<Object> getIterator(final Object[] array) {
return new Iterator<Object>() {
@Override
public boolean hasNext() {
// We do what is necessary
return false;
}
@Override
public Object next() {
// We do what is necessary
return null;
}
};
}
当然,这还有两个问题
当我们已经知道我们要做的就是调用Collection
方法时,iterator()
实现的重点是什么?为什么不首先调用getIterator
方法?
如果我们在这一点上,为什么不调用Arrays.asList(array).iterator()
(请记住,不复制数组)?
也就是说,拥有引用并不一定能防止垃圾回收。考虑The Java® Language Specification, §12.6.1:
可达对象是任何可以从任何活动线程继续计算中访问的对象。
...
可以设计优化程序的转换,以减少可达到的对象数量,使其少于可以被认为可达的对象数量。例如,Java编译器或代码生成器可以选择将不再用于
null
的变量或参数设置为使得此类对象的存储可能更快地回收。
请注意,这甚至适用于Iterator
实例,在将其代码内联到调用者(即循环)后可以回收其存储,以便它只在数组上工作。但是你不会注意到这一点,因为当然,优化器会确保程序的行为不会改变。