将Java';s垃圾收集器是否继续处理循环中声明的变量?

将Java';s垃圾收集器是否继续处理循环中声明的变量?,java,garbage-collection,Java,Garbage Collection,如果我有: for (int i; i != 100; i++) { ArrayList<String> myList = buildList(); //... more work here } for(int i;i!=100;i++){ ArrayList myList=buildList(); //……还有更多的工作要做 } 我是否必须在循环结束时将myList设置为null才能让GC回收它用于myList的内存?上帝,不!Java的GC比这聪明得多。GC将

如果我有:

for (int i; i != 100; i++) {
    ArrayList<String> myList = buildList();
    //... more work here
}
for(int i;i!=100;i++){
ArrayList myList=buildList();
//……还有更多的工作要做
}

我是否必须在循环结束时将myList设置为null才能让GC回收它用于myList的内存?

上帝,不!Java的GC比这聪明得多。

GC将自动清除任何不再在范围内的变量

在块内声明的变量(如for循环)将仅在该块内的作用域内。一旦代码退出块,GC将删除它。循环的迭代一结束就会发生这种情况,因此循环的每次迭代一结束,列表就有资格进行垃圾收集

变量的范围也是
i
在示例循环之后无效的原因


请注意,只有在循环中使用变量时才会出现这种情况。如果您将它传递给另一个保留对它的引用的方法,您的变量将不会被垃圾收集。

您不必担心垃圾。 javagc将自动执行此操作。 但我的建议是,作为一名优秀的开发人员,您必须进行实践 为了清理垃圾。 因为GC将需要一些处理时间。
因此,通过照顾好自己,我们一定会提高性能。

GC会在需要时回收所有无法访问的实例。它不包含GC变量

变量
i
myList
位于堆栈上。当for循环结束时(当它们超出范围时),它们将被从堆栈中推出,从而回收它们的内存。然后这些变量就会消失。在引用变量
myList
消失之前将其设置为null,实际上没有什么区别(对于GCing实例)。如果GC也会为引用的实例
myList
回收内存,这实际上取决于您是否有对同一实例的另一个引用


变量不会得到GCed,实例会得到GCed

了解for循环背后的语法可能会有所帮助。这一点在文章中讨论过

语句可以是单个语句或块(用大括号括起来的语句)。块表示一个新的词法作用域,其中声明的变量仅在该块的本地。许多人没有意识到的是,这并不是for循环所独有的。我可以将block语句放在方法中的任意位置:

 public void someMethod() {

     {
         List<String> myList = new ArrayList<String>();
         System.out.println(myList);
     }
     System.out.println(myList.size()); //compile error: myList out of scope
 }
public void someMethod(){
{
List myList=new ArrayList();
System.out.println(myList);
}
System.out.println(myList.size());//编译错误:myList超出范围
}

无论如何,这不是我想要的。只需说,它与它是一个循环这一事实关系不大,而与它是一个块这一事实关系更大(如果您选择不使用block语句,则无法声明新的局部变量,因此问题与此无关)

好吧,如果
buildList()
的结果覆盖
finalize()
它将是灾难性的。但我们希望代码是合理的。重写finalize()的对象会受到垃圾收集器的特殊处理。当然,但我想知道它是如何导致“灾难性”后果的。因为重写finalize的对象是与负责跟踪finalize之类的“finalizer对象”一起创建的。这会提高第0代集合的存活率,并将“终结器对象”推送到更高的世代,使它们更难收集。看看这里的例子:@Martinho:我看不出那篇文章中的任何内容是如何处理在循环中使用finalize方法的危险的,而是对
finalize()
的愚蠢实现的一般警告,无论是否在循环中。那么简单地重写
finalize()
怎么会导致灾难性的结果呢?我想他更担心的是,在以前的循环迭代中分配给
myList
的对象会被GC’d,即使仍然在循环中。我不知道这个答案是否足够完整。首先,整数和其他值类型在堆栈上分配,与垃圾收集无关。第二,myList可能有资格也可能没有资格进行垃圾收集;这取决于代码中是否有其他引用存储在其他地方。@取缔程序员:“在堆栈上分配整数和其他值类型”。你有这项索赔的证明人吗?我相信JVM可以选择是使用堆分配还是堆栈分配,并且会基于各种启发式方法来选择。或者你说的是基元类型?堆栈上的变量确实不会被垃圾收集,我只是指变量范围。我编辑了答案以提及其他参考文献,但这是我错过的一个非常好的观点。-1 GC不清理变量。GC与
i
无关,这是一个原始堆栈变量,而不是堆上的实例。这是否意味着GC不用于管理块内声明的变量/实例的内存?块结束后,变量/实例将自动回收?不,这并不意味着。实例仍然放在堆上并由gc回收。请记住,该块很容易泄漏对其中一个实例的引用。我想说的是,变量的作用域仅限于一个块,而与所使用的控制结构无关。
 public void someMethod() {

     {
         List<String> myList = new ArrayList<String>();
         System.out.println(myList);
     }
     System.out.println(myList.size()); //compile error: myList out of scope
 }