метод intern () влияет на производительность? - PullRequest
1 голос
/ 07 мая 2019

У меня есть некоторая путаница в отношении полезности метода intern().

Эта строка кода может очистить мою путаницу:

String a = new String("abc").intern();

Сколько объектов создаст строка кода выше? Если он создаст объект в памяти кучи, а также в памяти пула строк, то как метод intern() увеличивает производительность?

Ответы [ 2 ]

2 голосов
/ 07 мая 2019

Сколько объектов создаст строка кода выше?

  • Строковый литерал представлен во время выполнения одним String объектом. Если этот объект еще не был создан, то может быть создан (лениво) при выполнении этого оператора. В любом случае объект, представляющий литерал, будет интернирован. (Количество String объектов, созданных в этом процессе, является подробностью реализации, которая зависит от версии Java. Да, действительно.)

  • new String(...) создает объект каждый раз, когда вы его делаете.

  • Поскольку исходный объект String o был интернирован, вызов intern() вернет этот объект; то есть String, который представляет строковый литерал: тот, с которого вы начали.

Итак, в итоге ваш код может привести к созданию до трех объектов, непосредственно и за кулисами, но объект, созданный new, будет недоступен к концу оператора.

Действительно, с тех пор,

String a = new String("abc").intern();

и

String a = "abc";

дают идентичные результаты, последовательность new / intern - пустая трата времени.


Если он создаст объект в памяти кучи, а также в памяти пула строк, то как метод intern () увеличивает производительность?

Это не напрямую увеличивает производительность:

  • Существует потенциальная косвенная выгода, если вы можете интернировать все строки в структуре данных. Тогда вы можете использовать == вместо equals(Object) для проверки на равенство.

    Однако вы торгуете со стоимостью equals по сравнению со стоимостью, если intern, поэтому вам нужно сделать несколько сравнений объектов, прежде чем вы получите чистый выигрыш в производительности. Кроме того, если вы забудете интернировать одну из строк, == может дать вам другой ответ на equals. (Это, вероятно, ошибка!)

  • В старых JVM есть потенциальная косвенная выгода, если у вас много долгоживущих String объектов. Использование intern для дедупликации уменьшит долгосрочное использование памяти и уменьшит долгосрочные затраты на сборку мусора.

    Однако в недавних JVM GC будет автоматически de-dup String объектов, которые выдержат несколько циклов GC. Поскольку это только относится к относительно долгоживущим объектам, это более эффективный способ дедупликации. И процесс прозрачен для приложения!

Короче говоря, в большинстве случаев нет никаких преимуществ и существенных недостатков использования метода intern() в коде приложения. Оставь это.

1 голос
/ 07 мая 2019

У вас будет две строки:

  • "abc" - Строковый литерал.Он также добавляет «abc» в пул строк (см. Позже)
  • new String("abc") - новая копия «abc», созданная явно с новым оператором

Обратите внимание, что ничего не происходитдля вызова интерна, потому что строка "abc" уже присутствует в пуле строк с момента объявления строкового литерала.

Также присвоение не создает никакого нового объекта.

method intern:

Возвращает каноническое представление для строкового объекта.Пул строк, изначально пустой, поддерживается частным образом классом String.Когда вызывается метод intern, , если пул уже содержит строку, равную этому объекту String, как определено методом equals (Object), тогда строка из пула возвращается .В противном случае этот объект String добавляется в пул и возвращается ссылка на этот объект String.Отсюда следует, что для любых двух строк s и t s.intern () == t.intern () имеет значение true, если и только если s.equals (t) имеет значение true. Все литеральные строки и строковые константные выражения интернированы .Строковые литералы определены в разделе 3.10.5 Спецификации языка Java ™.

В этом контексте вызов intern не делает ничего полезного, поэтому у вас не будет никакого увеличения производительности.

...