Что такое пул строк в Java? [дубликат]
этот вопрос уже есть ответ здесь:
Я запутался в StringPool в Java. Я наткнулся на это, читая строковую главу на Java. Пожалуйста, помогите мне понять, в непрофессиональных терминах, что StringPool фактически делать.
4 ответов:
это выводит
true(даже если мы не используемequalsспособ: правильный способ сравнения строк)String s = "a" + "bc"; String t = "ab" + "c"; System.out.println(s == t);когда компилятор оптимизирует ваши строковые литералы, он видит, что как
sиtимеют одинаковое значение и поэтому вам нужен только один строковый объект. Это безопасно, потому чтоStringявляется неизменным в Java.
В результате, обаsиtуказывать на тот же объект и немного памяти.название 'string pool' происходит от идеи, что все уже определенные строки хранятся в некотором "пуле" и перед созданием нового
Stringобъект компилятор проверяет, если такая строка уже определена.
Я не думаю, что это на самом деле делает много, похоже, что это просто кэш для строковых литералов. Если у вас есть несколько строк, значения которых одинаковы, все они будут указывать на один и тот же строковый литерал в пуле строк.
String s1 = "Arul"; //case 1 String s2 = "Arul"; //case 2в случае 1 литерал s1 создается заново и хранится в пуле. Но в случае 2, литерал s2 ссылается на s1, он не будет создавать новый вместо этого.
if(s1 == s2) System.out.println("equal"); //Prints equal. String n1 = new String("Arul"); String n2 = new String("Arul"); if(n1 == n2) System.out.println("equal"); //No output.
давайте начнем с цитаты из спецификации виртуальной машины:
загрузка класса или интерфейса, который содержит строковый литерал, может создать новый строковый объект (§2.4.8) для представления этого литерала. Это может не произойти, если объект a String уже был создан для представления предыдущего вхождения этого литерала или если строка.метод intern был вызван для строкового объекта, представляющего ту же строку, что и буквальный.
это может не произойти - это намек, что есть что-то особенное
Stringобъекты. Обычно вызов конструктора будет всегда создать новый экземпляр класса. Это не относится к строкам, особенно когда строковые объекты "создаются" с помощью литералов. Эти строки хранятся в глобальном хранилище (пуле) - или, по крайней мере, ссылки хранятся в пуле, и всякий раз, когда новый экземпляр уже известных строк при необходимости виртуальная машина возвращает ссылку на объект из пула. В псевдо-коде это может выглядеть так:1: a := "one" --> if(pool[hash("one")] == null) // true pool[hash("one") --> "one"] return pool[hash("one")] 2: b := "one" --> if(pool[hash("one")] == null) // false, "one" already in pool pool[hash("one") --> "one"] return pool[hash("one")]так что в этом случае переменные
aиbсодержат ссылки на тот же
когда JVM загружает классы или иным образом видит литеральную строку или некоторый код
interns строка, он добавляет строку в основном скрытую таблицу поиска, которая имеет одну копию каждой такой строки. Если добавляется другая копия, среда выполнения организует ее так, чтобы все литералы ссылались на один и тот же строковый объект. Это называется "интернирование". Если вы говорите что-то вродеString s = "test"; return (s == "test");это
true, потому что первый и второй "тест" на самом деле один и тот же объект. Сравнение интернированных строк таким образом может быть много,много быстрееString.equals, так как есть одно сравнение ссылок, а не кучаcharсравнения.вы можете добавить строку в бассейн, вызвав
String.intern(), который вернет вам объединенную версию строки (которая может быть той же строкой, которую вы интернируете, но вы были бы сумасшедшими, чтобы полагаться на это-вы часто не можете точно знать, какой код был загружен и запущен до сих пор и интернирован той же строкой). Застаивание версия (строка, возвращенная изintern) будет равно любому идентичному литералу. Например:String s1 = "test"; String s2 = new String("test"); // "new String" guarantees a different object System.out.println(s1 == s2); // should print "false" s2 = s2.intern(); System.out.println(s1 == s2); // should print "true"
Comments