如果我有:
for (int i; i != 100; i++) {
ArrayList<String> myList = buildList();
//... more work here
}
我是否必须在循环结束时将myList设置为null以使GC回收它用于myList的内存?
答案 0 :(得分:10)
GC将自动清除不再在范围内的任何变量。
在块中声明的变量(例如for循环)将仅在该块内的范围内。代码退出块后,GC将删除它。只要循环的迭代结束,就会发生这种情况,因此只要循环的每次迭代结束,列表就有资格进行垃圾收集。
变量的范围也是在示例循环后i
无效的原因。
请注意,仅在循环内使用变量时才会出现这种情况。如果将其传递给另一个保持对它的引用的方法,则不会对您的变量进行垃圾回收。
答案 1 :(得分:5)
答案 2 :(得分:3)
GC会在需要时回收所有无法访问的实例。它不是GC变量。
变量i
和myList
存在于堆栈中。当for循环结束时(当它们超出范围时),它们将被推入堆栈,因此它们的内存被回收。然后变量就会消失。在它消失之前将引用变量myList
设置为null,实际上没有区别(对于GCing实例)。如果GC将回收引用的实例myList
的内存,实际上取决于您是否有另一个对同一实例的引用。
变量没有得到GCed,实例也没有。
答案 3 :(得分:3)
理解for循环的语法可能会有所帮助。这在JLS Section 14.14.1中讨论过。
BasicForStatement: for ( ForInitopt ; Expressionopt ; ForUpdateopt ) Statement ... Statement: StatementWithoutTrailingSubstatement ... StatementWithoutTrailingSubstatement: Block EmptyStatement ExpressionStatement ... Block: { BlockStatementsopt } BlockStatements: BlockStatement BlockStatements BlockStatement BlockStatement: LocalVariableDeclarationStatement ClassDeclaration Statement
语句一如既往,可以是单个语句或块(用大括号括起来的语句)。块表示新的词法范围,其中声明的变量仅对该块是本地的。许多人没有意识到的是,这并不是for循环所特有的。我可以在方法中的任何地方放置一个块语句:
public void someMethod() {
{
List<String> myList = new ArrayList<String>();
System.out.println(myList);
}
System.out.println(myList.size()); //compile error: myList out of scope
}
无论如何,这不是我打算去的地方。可以这么说,它与循环的关系较少,更多的是与它是块的事实有关(如果你选择不使用块语句,你不能声明新的局部变量,所以问题是无关)。
答案 4 :(得分:0)