сколько создается объектов и ссылок?

#java #string #object #heap-memory

Вопрос:

Я устал от этого фрагмента ниже и получил ответ в виде 3 объектов и 3 ссылок. Но в ключе ответа сказано, что это 4 объекта и 3 ссылки. Я в замешательстве, ошибся ли я или ключ к ответу. Пожалуйста, кто-нибудь, помогите.

 String str1=new String("Java"); //line 1
String str2=new String("GFT");  //line 2
String str3=str1;               //line 3 
str1=str1.concat(str2);         //line 4
str3=str2.toUpperCase();        //line 5
 

Объяснение моего ответа:

Ссылки: str1,str2,str3. Таким образом, количество ссылок=3.

Объекты: Количество изначально созданных объектов=0.

  • В строке 1 создается новый объект со значением «Java» и ссылкой «str1». Количество созданных объектов=1.
  • В строке 2 создается новый объект со значением «GFT» и ссылкой «str2». Количество созданных объектов=2.
  • Строка 3 создает новую ссылку «str3» , она не создает новый объект и указывает на объект, созданный в строке 1 (str1).
  • Строка 4 создает новый объект со значением «JavaGFT», и str1 теперь указывает на этот объект. Количество созданных объектов=3.
  • Строка 5 имеет значение «GFT», так как она уже присутствует, str3 теперь указывает на объект, созданный str2, поскольку str2 был создан с использованием нового оператора.( Я проверил, возвращает ли str2==str3 значение true), Поэтому, наконец, количество созданных объектов=3, количество ссылок=3.

Это правильно?

Ответ №1:

Поскольку существует только три уникальных имени переменных, и каждое имя переменной является ссылкой, вы правы, что существует три ссылки.

Однако в Java (и многих других языках) строки неизменяемы, что означает, что любая операция со строкой возвращает совершенно новую строку.

Ваше неправильное представление, похоже, с String.toUpperCase() вами . Если строка уже полностью прописная, то это вернет новую строку, равную исходной строке. Вы можете проверить это:

 String strA = "ABC";
String strB = strA.toUpperCase();
// two objects that are technically different, though they look and act the same as each other

print(strA == strB);       // false - they are not the same string 
print(strA.equals(strB));  // true  - however, they are equal to each other
 

В Java это будет справедливо для любого объекта* — == проверка сравнит расположение в памяти двух ссылок и вернет true , если они оба указывают на одно и то же место в памяти. Между тем, .equals() может быть настроено поведение для объекта. Если не переопределено, это возвращается к == проверке, но строка переопределяет это поведение и возвращает true , если строки идентичны.

Итак, всего создано четыре объекта:

  • new String("Java")
  • new String("GFT")
  • str1.concat(str2)
  • str2.toUpperCase() // идентичный str2 , но технически не один и тот же объект

*примечание: это не относится к примитивам int , таким как double , и т.д., У которых нет .equals() метода, потому что они не являются объектами.

Комментарии:

1. В моем тестировании кажется toUpperCase() , что он действительно вернется this , если он уже написан в верхнем регистре. По крайней мере, на OpenJDK 16. Другими словами, strA == strA.toUpperCase() возвращается true за мной.

2. Кроме того, new String("Java") если предположить "Java" , что он еще не интернирован, это приведет к созданию двух объектов. Это означает, что потенциально 6 объектов создаются примером кода операции.

3. Но str2 не был создан с помощью оператора=. Он был создан с использованием нового оператора . Поэтому, когда я запускаю его после выполнения функции toUpperCase (), str2==str3 возвращает значение true. Это означает, что они являются одними и теми же объектами, верно?

4. @Slaw Придирается new String("Java") : (интернированная) строка, представляющая "Java" литерал, не будет создана во время выполнения перечисленных инструкций, но заранее, скорее всего, во время загрузки/инициализации класса.