Когда меняется пул? - программирование

Когда меняется пул?

У меня есть два вопроса:

public static void main(String[] args) {
  String s1 = "bla";
  String s2 = "b" +"l" + "a";
  String s3 = "b".concat("l").concat("a");

  if(s1 == s2) 
        System.out.println("Equal");
  else
        System.out.println("Not equal");
  if(s1 == s3) 
        System.out.println("Equal");
  else
        System.out.println("Not equal");
}
  • Почему s1 и s2 указывают на один и тот же объект, тогда как s1 и s3 нет? (Нет использования ключевого слова new).

  • Если я получаю строку от пользователя и добавляю к вышеуказанному коду эти строки:

    BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
    String name=in.readLine();
    if(name.equals("test"))
        s1 = s1 + "xyz";
    

    Если пользователь входит xyz, программа будет печатать Not equal, когда пользователь вводит другую вещь, программа выводит Equal. Означает ли это, что пул изменяется через выполнение всей программы? Оптимизатор работает во время компиляции и продолжает работать в runtime?

4b9b3361

Ответ 1

Почему s1 и s2 указывают на один и тот же объект, а s1 и s3 - нет? (Нет использования нового ключевого слова).

Поскольку конкатенация происходит во время компиляции, и завершенная строка, следовательно, входит в пул констант так же, как в первом примере. Это специальный случай, "известный" компилятору. Это действительно означало, что длинные строки, объединенные таким образом по нескольким строкам, по-прежнему получают выгоду от тех же улучшений производительности, что и простые строковые константы.

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

Обратите внимание, однако, что в JLS детали того, что может и не может идти в пуле строковых констант, намеренно остаются неопределенными, поэтому различные реализации могут оптимизироваться по-разному. В нем указаны определенные правила относительно того, что должно там идти, но не полагайтесь на то, что это поведение является последовательным для всех реализаций.

Ответ 2

Почему s1 и s2 указывают на один и тот же объект, тогда как s1 и s3 не делает? (Нет использования нового ключевого слова).

Так как String в Java - это Immutable, поэтому любой метод строкового класса вернет новый объект String (хотя есть исключение - один - это метод substring). Следовательно, метод concat создает новую строку, которая отправляется в кучу, и не добавляется в постоянный пул.

Что касается случая s1 и s2, обе строки известны во время компиляции и, следовательно, это те же строковые литералы.

Обратите внимание, что операция конкатенации во второй строке: -

String s2 = "b" +"l" + "a";

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

Ответ 3

Иногда (когда для компилятора очевидно, что значение String будет во время выполнения), компилятор использует пул String, в других случаях это не так.

На самом деле ваш код не должен зависеть от факта использования или отсутствия пула.

Вы не всегда можете запустить main, поэтому, если вы хотите увидеть, используется ли ваша строка в пуле, вы можете декомпилировать код с помощью javap. Список является относительно понятным.