Ответ
В Java строки хранятся в пуле строк (String Pool), который находится в heap-памяти. При создании строки через литерал (String s = "text") JVM сначала проверяет наличие такой строки в пуле. Если строка существует, возвращается ссылка на неё, иначе — создаётся новый объект.
При использовании конструктора (new String("text")) всегда создаётся новый объект в куче, даже если такая строка есть в пуле. Для ручного добавления строки в пул используется метод intern().
Пример:
String s1 = "hello"; // в пуле
String s2 = new String("hello"); // в куче
String s3 = s2.intern(); // вернёт ссылку на s1 из пула