опубликовано Нареш Джоши 17 февраля 2018 г.
В предыдущей статье Почему String является неизменяемой и финальной в Java я обсуждал, почему String неизменяем по своей природе, а также преимущества и недостатки неизменности String. Я также обсуждал, что все строковые литералы кэшируются в специальной области памяти, называемой пулом строковых констант, и как неизменяемость String сделала возможным создание пула констант String.
Но возникает вопрос, почему в Java требуется отдельный постоянный пул для хранения строк, в чем причина, почему строки не хранятся в обычной куче памяти, как это делают другие объекты, и в этой статье я постараюсь ответить на эти вопросы.
Что ж, мы знаем, что String — самый популярный тип, представленный в Java, и почти все Java-программы используют его. На самом деле я не видел ни одной Java-программы, написанной без использования String. В общем, обычное бизнес-приложение Java имеет дело с тысячами строковых объектов, многие из них имеют одно и то же связанное значение, и многие из них являются промежуточными операциями. Строка означает, что они не являются окончательным результатом. Поэтому, если мы будем хранить все эти строковые объекты в обычной памяти кучи, большая часть кучи будет занята только строковыми объектами, и сборщику мусора придется запускаться чаще, что снизит производительность приложения.
И именно поэтому у нас есть String Constant Pool и процесс интернирования String, всякий раз, когда мы создаем строковый литерал, JVM сначала видит, присутствует ли этот литерал уже в пуле констант или нет, и если он там, новая переменная начнет указывать на тот же объект , этот процесс называется Интернирование строк.
Есть два способа создать объект String
- Создание строкового литерала:: все, что подпадает под
""
, является строковым литералом, например.String s1 = "Naresh"
, по умолчанию все строковые литералы интернируются и уходят в SCP. - Создание объекта String с помощью конструктора: Если мы создадим объект String с помощью конструктора, например.
String s2 = new String("Naresh")
объект создается в обычной динамической памяти вместо SCP. И именно поэтому создание объекта String с использованием конструктора не считается лучшей практикой. Мы можем попросить s2 указать на SCP вместо обычной кучи вручную, вызвав для него методintern()
, то есть s2.intern().
Таким образом, чтобы сохранить память, потребляемую строковыми объектами, Java позволяет нескольким ссылочным переменным указывать на один и тот же объект, если они имеют одинаковое значение. Вот почему создатели JVM создали отдельную область памяти SCP для строковых литералов и установили правило, согласно которому, если несколько строковых переменных содержат одно и то же значение, они будут указывать на один и тот же объект.
String a = "Naresh";
String b = "Naresh";
String c = "Naresh";
Для приведенного выше кода будет создан только один объект Naresh
, и все ссылочные переменные a
, b
, c
будут указывать на один и тот же объект.
В приведенном выше примере строковый объект со значением Naresh
будет создан в SCP только один раз, и все ссылки a
, b
, c
будут указывать на один и тот же объект, но что, если мы попытаемся внести изменения в a
, например. a.replace("a", "")
.
В идеале a
должно иметь значение Nresh
, но b
, c
должны оставаться неизменными, поскольку мы, как конечный пользователь, вносим изменения только в a
. И мы знаем, что a
, b
, c
все указывают на один и тот же объект, поэтому, если мы внесем изменение в a
, другие также должны отразить это изменение.
Но неизменяемость строки спасает нас от этого сценария, и благодаря неизменности строкового объекта строковый объект Naresh
никогда не изменится. Поэтому, когда мы вносим какие-либо изменения в a
вместо изменения строкового объекта Naresh
, JVM создает новый объект, назначая его a
, а затем вносит изменения в этот объект.
Таким образом, пул строк возможен только из-за неизменяемости String, и если бы String не была неизменной, то кэширование строковых объектов и их повторное использование было бы невозможно, потому что любая переменная изменила бы значение и испортила другие.
Вы можете найти полный код в этом репозитории Github и, пожалуйста, не стесняйтесь оставлять свои ценные отзывы.
Первоначально опубликовано на www.programmingmitra.com.