String pool java что это
Перейти к содержимому

String pool java что это

  • автор:

String Pool в Java

Anver Bogatov

Java даёт выбор между примитивными типами данных и объектными. Одни передаются по значению, другие по ссылке. Одни занимают предсказуемое количество памяти, другие не очень (конечно только если Вы не знаете размеры метаинформации класса, для которого хотите произвести расчёт). Под одних память выделяется на стеке, под другие в heap’е. Они сильно отличаются друг от друга

Элементы в пределах своего типа (примитивный или объектный) ведут себя похоже, независимо от конкретного типа данных. Значения int ведут себя так же, как и значения типа short. В объектных типах данных схожая ситуация. Но есть исключения. Например — объектный тип String.

Что такое String?

String — это класс в Java, то есть объектный тип. Он описывает строки и хранит их данные в массиве char.

Оговорка:
Тип char используется в старых версиях Java, например 8-ой. В Java 11 используется уже массив byte’ов.

Сколько памяти занимает String? Примитивный тип char в Java имеет размер 2 byte’а. То есть один символ занимает в памяти 2 байта. Теперь представьте — каждый раз когда мы используем строку в Java, будь-то имя пользователя или ссылку на какой-либо сайт, мы создаём в системе большой массив char. Это занимает память. В объектных типах помимо всех ссылок на объекты и примитивов, память занимает ещё и заголовочная информация класса.

Зачем это знать? Строки — самый популярный тип данных в Java. Огромное количество данных описывается строками. Ещё более интересн тот факт, что строки в одних и тех же программах часто повторяются.

String — это immutable тип. То есть, после создания объекта этого типа поменять его значение нельзя. Отсюда делаем вывод — смысла в создании новых объектов типа String со значениями, для которых объекты уже были созданы — нет. Это не целесообразно, потому что каждый раз выделять память под одно и тоже, что ещё и не возможно изменить — чревато чрезмерным потреблением памяти.

Создатели Java заранее позаботились об этой проблеме и сделали тип String не совсем обычным объектным типом.

Что такое строковый пул?

Строковый пул или String pool — это особое место в heap’е, куда попадают объекты типа String после их создания. Он выполняет функцию кеша строк. Каждый раз, когда Вы создаёте строку, она попадает в строковый пул. Если же на момент создания новой строки пул уже содержит такое же значение, то вместо создания нового объекта возвращается тот, что уже лежит в пуле.

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

Как работать со строковым пулом?

Разберёмся с тем как работает String pool на практике.

Обычно строки в Java программах объявляются так:

Что происходит в JVM за кадром? Остановитесь и подумайте. Если Вашим ответом будет что-то вроде — «В heap’е будет выделена память под строковый объект и ссылка на него будет возвращена и присвоена локальной переменной text» — Вы правы.

А что произойдёт тут? Если Вы думаете, что на обе локальные переменные будет выделена память в heap’е — Вы ошибаетесь. Именно в этом примере и видно результат работы пула строк.

В Java все строки, объявленные в виде литералов, то есть так:

автоматически попадают в строковый пул. Любая попытка объявить новую переменную задав ей значение с помощью литерала приводит к тому, что JVM проверяет наличие такой строки в пуле строк и возвращает объект из него, если объект с таким значением обнаружен.

Как убедиться в том, действительно ли обе переменные указывают на один и тот же объект? Очень просто. Достаточно посмотреть что будет выведено в результате следующей операции:

Не спешите набирать код, я Вам подскажу — ответом будет `true`. Это означает — обе переменные указывают на один и тот же объект.

А как тогда сделать так, чтобы строки в пул не попадали? Это тоже сделать просто. Используйте конструктор явно при создании строк. Вот так:

В этом случае, объект типа String будет создан, память под него будет выделена в heap’е, но в строковый пул он не попадёт. Это легко проверяется следующим примером:

Результатом работы кода выше будет `false`, потому что теперь ссылки указывают на два разных объекта.

Ну и наконец, как добавить строку в строковый пул после её создания? Для этого класс String содержит метод под названием `intern()`. Именно он отвечает за сохранение текущего объекта String в пул строк. Пример использования:

Зачем знать о строковом пуле?

Строковый пул несёт не только пользу. Если не знать о его существовании и принципах работы, можно легко получить дыру в безопасности приложения. Сделать это довольно просто — достаточно добавить в пул какой-нибудь пароль или логин. Содержимое строкового пула доступно в memory dump’ах, к которым Вы или кто-то другой может получить доступ.

Надеюсь эта статья поможет Вам писать код более осознанно, ведь, теперь Вы знаете, что за строками в Java стоит String pool.

Java Challengers #2: Сравнение строк

У нас как всегда много опаздывающих к началу курса, так что только вчера провели второе занятие среди нового потока «Разработчик Java». Но это так, мелочи жизни, а пока что мы продолжаем публикацию серии статей Java Challengers, перевод которых подготовили для вас.

В Java класс String инкапсулирует массив char (прим. переводчика — с java 9 это уже массив byte , см. Компактные строки в Java 9). Говоря по простому, String — это массив символов, используемый для составления слов, предложений или других конструкций.

Инкапсуляция — это одна из самых мощных концепций объектно — ориентированного программирования. Благодаря инкапсуляции вам не нужно знать как работает класс String . Вам достаточно знать методы его интерфейса.

Когда вы смотрите на класс String в Java, вы можете увидеть как инкапсулирован массив char :

Чтобы лучше понять инкапсуляцию, представьте физический объект: машину. Нужно ли вам знать, как работает автомобиль под капотом, чтобы управлять им? Конечно, нет, но вы должны знать, что делают интерфейсы автомобиля: педаль газа, тормоза и рулевое колесо. Каждый из этих интерфейсов поддерживает определенные действия: ускорение, торможение, поворот налево, поворот направо. То же самое и в объектно — ориентированном программировании.

Первая статья в серии Java Challengers была про перегрузку методов, которая широко используется в классе String . Перегрузка может сделать ваши классы действительно гибкими:

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

Что такое пул строк (String pool)

Класс String , возможно, наиболее часто используемый класс в Java. Если новый объект создавать в динамической памяти (memory heap) каждый раз, когда мы используем String , то мы потратим впустую много памяти. Пул строк (String pool) решает эту проблему, сохраняя только один объект для каждого значения строки.

strings-in-the-string-pool

Строки в пуле строк

Хотя мы создали несколько переменных String со значениями Duke и Juggy , но в динамической памяти (куче) создаётся и храниться только два объекта. Для доказательства посмотрите следующий пример кода. (Напомним, что в Java оператор » == » используется для сравнения двух объектов и определения того один и тот же это объект или нет.)

Этот код вернет true , потому что две переменные String указывают на один и тот же объект в пуле строк. Их значения одинаковые.

Исключение — оператор new

Теперь посмотрите на этот код — он выглядит похожим на предыдущий пример, но здесь есть отличие.

На основе предыдущего примера можно подумать, что этот код вернёт true , но это не так. Добавление оператора new приводит к созданию нового объекта String в памяти. Таким образом, JVM создаст два разных объекта.

Native-методы в Java — это методы, которые будут компилироваться с использованием языка C, обычно с целью управления памятью и оптимизации производительности.

Пулы строк и метод intern()

Для хранения строк в пуле используется способ, называемый «интернирование строк» (String interning).

Вот, что Javadoc говорит нам о методе intern() :

Метод intern() используется для хранения строк в пуле строк. Во-первых, он проверяет, существует ли уже созданная строка в пуле. Если нет, то создает новую строку в пуле. Логика пула строк основана на паттерне Flyweight.

Теперь, обратите внимание, что происходит, когда мы используем new для создания двух строк:

В отличие от предыдущего примера с ключевым словом new , в данном случае сравнение вернёт true . Это потому, что использование метода intern() гарантирует, что строка будет в пуле.

Метод equals в классе String

Метод equals() используется для того, чтобы проверить одинаковое или нет состояние двух классов. Поскольку equals() находится к классе Object , то каждый Java — класс наследует его. Но метод equals() должен быть переопределен, чтобы он работал правильно. Конечно, String переопределяет equals() .

Как вы видите, значение класса String сравнивается через equals() , а не через ссылку на объект. Не имеет значения, если ссылки на объекты разные; будут сравниваться состояния.

Наиболее распространенные методы String

Есть ещё одна вещь, которую вам нужно знать, прежде чем решить задачку на сравнение строк.

Рассмотрим наиболее распространённые методы класса String :

Решите задачку на сравнение строк

Давайте проверим, что вы узнали о классе String , решив небольшую задачку.

В этой задаче вы сравните несколько строк, используя изученные концепции. Глядя на код ниже, можете ли вы определить значение каждой переменной result ?

Какой будет вывод?

  • A: 02468
  • B: 12469
  • C: 12579
  • D: 12568

Правильный ответ приведён в конце статьи.

Что сейчас произошло? Понимание поведения String

В первой строке мы видим:

В этом случае результат false , потому что, когда метод trim() удаляет пробелы он создаёт новый String с помощью оператора new .

Здесь нет никакой тайны, строки одинаковы в пуле строк. Это сравнение возвращает true .

Использование new приводит к созданию двух новых строк и не важно равны их значения или нет. В этом случае сравнение будет false даже если значения одинаковые.

Поскольку мы использовали метод equals() , будет сравниваться значение строки, а не экземпляр объекта.

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

Окончательно, мы имеем:

Как вы видели ранее, метод intern() помещает строку в пул строк. Обе строки указывают на один и тот же объект, поэтому в этом случае true .

Распространенные ошибки со строками

Бывает трудно определить, указывают ли две строки на один и тот же объект или нет, особенно когда строки содержат одно и то же значение. Полезно помнить, что использование new всегда приводит к созданию нового объекта в памяти, даже если значения строк одинаковые.

Использование методов класса String для сравнения ссылок на объекты также может быть сложным. Особенность в том, что если метод изменяет что-то в строке, то будут разные ссылки на объекты.

Несколько примеров, которые помогут прояснить:

Это сравнение будет истинным, потому что метод trim() не создает новую строку.

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

Наконец, когда trim() выполнит свою работу, он создает новую строку:

Что нужно помнить о строках

Строки не изменяемые, поэтому состояние строки изменить нельзя.

Для экономии памяти JVM хранит строки в пуле строк. При создании новой строки JVM проверяет ее значение и указывает на существующий объект. Если в пуле нет строки с этим значением, то JVM создаёт новую строку.

Оператор » == » сравнивает ссылки на объект. Метод equals() сравнивает значения строк. То же правило будет применяться ко всем объектам.

При использовании оператора new будет создана новая строка в хипе (Прим. переводчика — в оригинале написано, что в пуле, но это не так, спасибо zagayevskiy), даже если есть строка с тем же значением.

What is Java String Pool?

What is Java String Pool?

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

As the name suggests, String Pool in java is a pool of Strings stored in Java Heap Memory. We know that String is a special class in java and we can create String objects using a new operator as well as providing values in double-quotes.

String Pool in Java

Here is a diagram that clearly explains how String Pool is maintained in java heap space and what happens when we use different ways to create Strings. String Pool in Java, string pool, java string pool String Pool is possible only because String is immutable in Java and its implementation of String interning concept. String pool is also example of Flyweight design pattern. String pool helps in saving a lot of space for Java Runtime although it takes more time to create the String. When we use double quotes to create a String, it first looks for String with the same value in the String pool, if found it just returns the reference else it creates a new String in the pool and then returns the reference. However using new operator, we force String class to create a new String object in heap space. We can use intern() method to put it into the pool or refer to another String object from the string pool having the same value. Here is the java program for the String Pool image:

Output of the above program is:

Recommended Read: Java String Class

How many Strings are getting Created in the String Pool?

Sometimes in java interview, you will be asked a question around String pool. For example, how many strings are getting created in the below statement;

In the above statement, either 1 or 2 string will be created. If there is already a string literal “Cat” in the pool, then only one string “str” will be created in the pool. If there is no string literal “Cat” in the pool, then it will be first created in the pool and then in the heap space, so a total of 2 string objects will be created. Read: Java String Interview Questions

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Что такое пул строк в Java?

Пул строк (String Pool) — это множество строк в кучи (Java Heap Memory). Мы знаем, что String — особый класс в java, с помощью которого мы можем создавать строковые объекты.

На диаграмме ниже мы видим как именно строковый пул расположен в памяти Java Heap. И как разные способы создания строк влияют на расположение их в памяти.

String Pool Java Javadevblog.com

Сам строковый пул возможен только потому, что строки в Java неизменные. Также пул строк позволяет сохранить память в Java Runtime, хотя это и требует больше времени на создание самой строки.

Пример работы с пулом строк

Когда мы используем двойные кавычки, чтобы создать новую строку, то первым делом идет поиск строки с таким же значением в пуле строк. Если java такую строку нашла, то возвращает ссылку, в противном случае создается новая строка в пуле, а затем возвращается ссылка.

Однако использование оператора new заставляет класс String создать новый объект String. После этого можем использовать метод intern() , чтобы поместить этот объект в пул строк или обратиться к другому объекту из пула строк, который имеет такое же значение.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *