Ответ 1
Теперь в случае строки это не так, потому что строка попадет в пул строк, а JVM сохранит объект для повторного использования. Значит, однажды созданная строка "никогда" не будет собираться мусором?
Во-первых, только строковые литералы (см. примечания) автоматически интернируются/добавляются в пул строк. String
объекты, созданные приложением во время выполнения, не интернируются... если только ваше приложение явно не вызывает String.intern()
.
Во-вторых, на самом деле правила для объектов сбора мусора в пуле строк такие же, как и для других объектов String
: на самом деле все объекты. Они будут собирать мусор, если они когда-нибудь станут недоступными.
На практике объекты String
, которые соответствуют строковым литералам, обычно не становятся кандидатами на сборку мусора. Это связано с тем, что в коде каждого метода, использующего литерал, имеется неявная ссылка на объект String
. Это означает, что String
достижимо до тех пор, пока метод может быть выполнен.
Тем не менее, это не всегда так. Если строковый литерал был определен в классе, который был динамически загружен (например, с помощью Class.forName(...)
), то можно договориться о том, чтобы класс был выгружен. Если это произойдет, тогда объект String
, соответствующий литералу, может быть недоступным и, в конечном счете, может быть GC-кодом.
См. также: Когда и как мусор классов собирается в Java?
Примечания:
Строковый литерал (JLS 3.10.5) - это строка, которая появляется в исходном коде Java; например,
"abc" // string literal new String(...) // not a string literal
Строка, полученная вычислением константного выражения (во время компиляции) (JLS 15.28), также может быть интернирована.
"abc" + 123 // 123 is a constant expression "abc" + Integer.valueOf(123) // Integer.valueOf(123) is also // a constant expression
Строго говоря, не все строковые литералы интернированы. Если литерал String появляется только в исходном коде как подвыражение константного выражения, этот литерал может не отображаться в файле ".class" ни в какой форме. Такой литерал не будет интернирован, потому что он не будет существовать во время выполнения.