Я не согласен с принятым ответом. Я считаю, что ваш ответ пяти объектов, имеющих право на сбор мусора, на самом деле правильный, и упражнение, из которого вы работаете, неверно (хотя, если кто-нибудь может объяснить, как я ошибаюсь, я бы очень признателен).
Вот объекты, на которые ссылаются программе:
Integer
# 0 - The Integer
создан static Integer value = new Integer()
*
Currency
# 1 - Currency
созданный Currency.getCurrency(50)
.
Integer
# 1 - Integer
, возвращенный автообоксированием 50
.
String
# 1 - String
создатель: String name = new String()
в Currency
# 1 создание.
Currency
# 2 - Currency
создатель: Currency.getCurrency(100)
.
Integer
# 2 - Integer
, возвращенный автообоксированием 100
.
String
# 2 - String
создатель: String name = new String()
в Currency
# 2 создание.
* Это фактически не компилируется, но я предполагаю, что он заменен действительным кодом, который не влияет на программу.
Таким образом, для вашего кода необходимо семь объектов. Первоначально объект, на который ссылается value
, получает право на сбор мусора, когда value
заменяется на 50
. Первый и второй Currency
s имеют право на конец m
, когда их единственные ссылки выходят за рамки. Первый и второй String
s имеют право на конец m
, когда их только объекты-ссылки, Currency
с 1 и 2, выходят за рамки. Автобокс Integer
от 100
, очевидно, по-прежнему ссылается в конце на статическую ссылку value
и поэтому не имеет права на сбор мусора. Это 5 объектов, имеющих право на участие, 1 неприемлемых и еще не обсужденных.
Последний объект: Integer
, возвращенный autoboxing из 50
. Ваш код, очевидно, больше не ссылается на него, так как value
вместо этого ссылается на 100
. Это, по-видимому, указывает на то, что оно имеет право на сбор мусора, но я не согласен. Integer
класс is know to cache values at least in the range -128
to 127
, чтобы соответствовать JLS 5.1.7. Поэтому, когда выйдет m
, кеш по-прежнему будет содержать ссылку на коробку Integer
от 50
, в результате чего она будет непригодна для сбора мусора.
Я попытался проверить это поведение с помощью этой программы:
public class Test{
public static final WeakReference<Integer> inCache = new WeakReference<>(50);
public static final WeakReference<Integer> outOfCache = new WeakReference<>(10000);
public static void main(String[] args){
System.gc();
System.out.println(inCache.get());
System.out.println(outOfCache.get());
}
}
который выводит
50
null
, показывающий, что, по крайней мере, в этом случае, Uncached Integer
был мусора и кешированного не было. Это говорит о том, что даже без явной ссылки на 50
он по-прежнему не подходит для сбора мусора из-за хранимой ссылки в кеше.
Я признаю, что это ничего не доказывает, так как для одного System.gc()
не гарантирует, что он будет собирать всю (или любую) доступную память. Тем не менее, я думаю, это должно показать, что проблема не такая простая, как можно было бы предположить, и, по наиболее распространенным JDK/JVM, вполне вероятно, что шестое значение не подходит для сбора мусора.
TL; DR - Я не думаю, что Integer
возвращаемый бокс 50
имеет право на сбор мусора, потому что она по-прежнему ссылается на кэш, поддерживаемой Integer
класса.
Можете ли вы рассказать нам, какие 5 переменных вы считали подходящими для сбора мусора? –
Два объекта «Валюта», созданных в getCurrency, для каждого из этих объектов в куче создается строка «имя» (нестатическая). Затем я подумал, что c.value просто изменит содержимое статического целочисленного значения, но похоже, что я ошибаюсь в этой последней части? – user1365914
Это вопрос трюка: никакие объекты не подходят для GC, потому что не создаются никакие объекты, учитывая, что 'new Integer()' вызывает 'Ошибка компиляции конструктора Integer() не определена, и, следовательно, предотвращает запуск кода. – Andreas