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

Я запутался в StringPool в Java. Я натолкнулся на это, читая главу String на Java. Пожалуйста, помогите мне понять, на простых условиях, что на самом деле делает StringPool.

Это выводит true (хотя мы не используем метод equals : правильный способ сравнения строк)

  String s = "a" + "bc"; String t = "ab" + "c"; System.out.println(s == t); 

Когда компилятор оптимизирует ваши строковые литералы, он видит, что и s и t имеют одинаковое значение и, следовательно, вам нужен только один строковый объект. Это безопасно, потому что String неизменна в Java.
Как результат, и s и t указывают на один и тот же объект и небольшую память.

Имя «пул строк» ​​исходит из идеи, что вся уже определенная строка хранится в некотором «пуле» и до создания нового компилятора объекта 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. 

http://p2p.wrox.com/java-espanol/29312-string-pooling.html

Начнем с цитаты из спецификации виртуальной машины:

Загрузка classа или интерфейса, который содержит строковый литерал, может создать новый объект String (§2.4.8) для представления этого литерала. Это может не произойти, если объект String уже создан для представления предыдущего вхождения этого литерала или если метод String.intern был вызван на объект String, представляющий ту же строку, что и литерал.

Это может не произойти – это намек на то, что есть что-то особенное в объектах String . Обычно вызов конструктора всегда создает новый экземпляр classа. Это не относится к строкам, особенно когда объекты String «созданы» с литералами. Эти строки хранятся в глобальном хранилище (пуле) – или, по крайней мере, ссылки хранятся в пуле, и всякий раз, когда требуется новый экземпляр уже известных строк, vm возвращает ссылку на объект из пула. В псевдокоде это может выглядеть так:

 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 содержат ссылки на один и тот же объект. В этом случае мы имеем (a == b) && (a.equals(b)) == true .

Это не так, если мы используем конструктор:

 1: a := "one" 2: b := new String("one") 

Опять же, "one" создается в пуле, но затем мы создаем новый экземпляр из одного и того же литерала, и в этом случае он приводит к (a == b) && (a.equals(b)) == false

Итак, почему у нас есть пул строк? Строки и особенно строковые литералы широко используются в типичном Java-коде. И они неизменны. И быть неизменным разрешено кэшировать String для экономии памяти и повышения производительности (меньше усилий для создания, меньше мусора, который нужно собрать).

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

  • (a == b) && (a.equals(b)) может быть true или false ( всегда использовать equals для сравнения строк)
  • Не использовать reflection , чтобы изменить защитный char[] из строки (как вы не знаете , кто actualling с помощью этой строки)

Когда JVM загружает classы или иным образом видит литеральную строку или некоторую строку кода sa sa sa, она добавляет строку в почти скрытую таблицу поиска, которая имеет одну копию каждой такой строки. Если добавлена ​​другая копия, среда выполнения упорядочивает ее так, чтобы все литералы ссылались на один и тот же строковый объект. Это называется «интернированием». Если вы скажете что-то вроде

 String s = "test"; return (s == "test"); 

он вернет true , потому что первый и второй «тест» на самом деле являются одним и тем же объектом. Сравнение интернированных строк таким образом может быть намного, намного быстрее, чем String.equals , так как существует только одно сравнительное сравнение, а не сравнение 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" 
  • Как установить -source 1.7 в Android Studio и Gradle
  • java.io.IOException: обнаружено не было
  • Служба Android должна запускаться всегда (никогда не останавливать или останавливать)
  • java.net.UnknownHostException: Недопустимое имя хоста для сервера: local
  • getExtractedText на неактивное предупреждение InputConnection на Android
  • Почему вызовы метода интерфейса медленнее, чем конкретные вызовы?
  • HashMap: один ключ, несколько значений
  • Метод getText () должен быть вызван из streamа пользовательского интерфейса (Android Studio)
  • Android View исчезает, когда выходит за пределы родителя
  • Android получает дату до 7 дней (одна неделя)
  • Почему в Android не работает «System.out.println»?
  • Давайте будем гением компьютера.