Пример вашего учителя не очень хорош, потому что i
, вероятно, хранится в стеке, так как это примитив.Лучшим примером будет:
public String helloWorld() {
StringBuilder builder = new StringBuilder();
builder.append("Hello");
builder.append(" ");
builder.append("World!");
return builder.toString();
}
В первой строке функции мы выделяем новый объект (new StringBuilder()
).Это выделяет некоторую память в куче , которая впоследствии должна быть освобождена.В C ++ вы бы сделали delete builder
в конце, чтобы обработать это (или выделить его в стеке - но вы не можете сделать это в Java, поэтому я думаю, что это разумный пример).
Сборка мусора - это альтернативный метод, в котором ничего не происходит с builder
в конце функции.Вместо этого периодически запускается процесс, называемый сборщиком мусора, который проверяет, какие объекты используются или не используются, и избавляется от всего, что не является.В примере, который я привел, сборщик мусора запустится, заметит, что больше нет способа получить доступ к builder
и удалить его.
Сборщик мусора по умолчанию в Java выполняет то, что называется «пометить и очистить», где он в основномпросматривает все переменные, к которым имеет доступ, и отмечает их (установлен некоторый флаг).Затем он удаляет все, что не помечено.
Я думаю, что на еще более низком уровне он фактически перемещает все доступное в новую область памяти и удаляет все в старой области памяти (потому что все еще тамне был доступен).
Более простой метод сбора мусора называется «подсчет ссылок», где все, что динамически размещается, имеет счетчик ссылок - сообщая программе, сколько переменных указано в этом месте памяти.Если счетчик ссылок когда-либо достигнет 0, никто не использует эту память, и она может быть немедленно освобождена.В прошлый раз, когда я проверял, стандартный интерпретатор Python (CPython) использует это.
Проблема с подсчетом ссылок заключается в том, что вы можете получить циклы:
class Node {
Node next;
}
public void breakReferenceCountingAlgorithm() {
Node a = new Node();
Node b = new Node();
a.next = b;
b.next = a;
}
В конце этой функциии b оба ссылаются один раз (друг на друга), но они не доступны.Ява поймает это и мусор собирает их так или иначе.Python не будет.
С другой стороны, причина, по которой вы не можете использовать i
вне того цикла, который вы задали, - это область видимости, а не сборка мусора.Внутри функции память i
, вероятно, все еще доступна, компилятор просто не позволит вам получить к ней доступ.В основном, чтобы вы могли сделать это:
for(int i = 0; i < 100; i++) {
System.out.println("stuff");
}
// This i is a different variable
for(int i = 0; i < 100; i++) {
System.out.println("more stuff");
}