#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"
литерал, не будет создана во время выполнения перечисленных инструкций, но заранее, скорее всего, во время загрузки/инициализации класса.