Java String как получить ссылку?

Не подскажите как получить ссылку на обьект в пуле стрингов на определенную строку? Например когда мы создаем обьект его дефолтный метод toString выдает его сcылку скажем "Person@2f92e0f4", а как получить ссылку на обьект в пуле стрингов?

Updated: Я проходил собеседование в Сбербанк, и там был такой вопрос:

String s1="Hello";
String s2="Hello";
String s3=new String("Hello");
String s4=new String("Hello");
System.out.println(s1==s2);
System.out.println(s2==s3);
System.out.println(s3==s4);

Что выведется в консоль? правильный вариант ответа:

true false false

Это все было в виде теста с вариантами ответов. Насчет s1==s2 понятно ведь джава проверяет есть ли такая строка в пуле или нет, если нет создает новую, если да то просто в s2 копируется ссылка s1 на эту же строку в пуле стрингов. Но почему s3==s4 false? как посмотреть ссылки на эти обьекты?


Ответы (1 шт):

Автор решения: Михаил Ребров

Описанный вами вопрос касался не всех объектов, а особенностей хранения строк в памяти.

Смысл в том, что строки созданные с помощью конструктора и строковые литералы хранятся немного по разному.

  • Строки созданные с помощью конструктора, как и полагается, хранятся в куче(Java Heap Memory)
  • Строковые литералы же хранятся в специально отведенном месте, которое называется пул строк(String Pool)

Задача String Pool - эффективная работа со строками и оптимизация их хранения.

В вашем примере

String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
String s4 = new String("Hello");

Идем с начала.

  1. У вас появляется литерал "Hello", который попадает в String Pool
  2. Далее Вы кладёте в переменную s1 ссылку на "Hello" в String Pool
  3. Далее при использовании того же литерала "Hello" вы получаете ту же ссылку на то же место в String Pool (и это одна из его задач: чтобы не забивать всю память одними и теми же литералами)
  4. После чего Вы кладёте ту же ссылку на то же место в переменную s2, после чего переменные s1 и s2 хранят одинаковые ссылки, которые ведут в String Pool
  5. Далее Вы создаете объект с помощью конструктора и он уже размещает значение переменной не в String Pool, а в общей области Java Heap Memory
  6. Тоже самое происходит с переменной s4

В итоге получается, что:
Переменные s1 и s2 ссылаются на один и тот же участок памяти специально созданный для оптизации хранения строковых литералов.
А под переменные s3 и s4 выделялись отдельные участки памяти(для каждой) в куче(Java Heap Memory)

Что и соответствует выводу

true
false
false

Перемещение строк в String Pool

Также стоит понимать, что вы можете переместить строки созданные с помощью конструктора в пул строк.

Для этого есть метод intern() который перемещает строку в String Pool и возвращает ссылку на аналогичную строку в пуле, при этом если такая строка уже была в пуле, то вы получите ссылку на нее.

И если мы попробуем сделать так

String s1 = "Hello";
String s2 = "Hello";
String s3 = (new String("Hello")).intern();
String s4 = (new String("Hello")).intern();

System.out.println(s1==s2);
System.out.println(s2==s3);
System.out.println(s3==s4);

то на выводе получим, что все они равны

true
true
true

введите сюда описание изображения


Подробнее:

→ Ссылка