Есть ли разница между String concat и оператором + в Java?
Duplicate
java Конкатенация строк
Мне любопытно, в чем разница между ними.
То, как я понимаю пул строк, таков:
Это создает 3 строковых объекта в пуле строк, поскольку 2 из этих ссылок теряются.
String mystr = "str";
mystr += "end";
Не создает ли это также 3 объекта в пуле строк?
String mystr = "str";
mystr = mystr.concat("end")
Я знаю, что StringBuilder и StringBuffer намного эффективнее с точки зрения использования памяти, когда нужно много конкатенировать. Мне просто интересно, есть ли разница между оператором + и concat с точки зрения использования памяти.
Ответы
Ответ 1
В этом конкретном случае нет никакой разницы; , однако они не совпадают в целом.
str1 += str2
эквивалентно выполнению следующего:
str1 = new StringBuilder().append(str1).append(str2).toString();
Чтобы доказать это самому себе, просто сделайте простой метод, который берет две строки и +=
первую строку ко второй, затем исследует дизассемблированный байт-код.
В отличие от этого, str1.concat(str2)
просто создает новую строку, которая объединяет str1
и str2
, что является менее дорогостоящим для небольшого количества конкатенированных строк (но проиграет первый подход с большим числом).
Кроме того, если str1
равно null, обратите внимание, что str1.concat(str2)
выбрасывает NPE, но str1 += str2
будет просто рассматривать str1
так, как если бы он был нулевым, не выбрасывая исключение. (То есть, он дает "null", объединенный со значением str2
. Если str2
были, скажем, "foo", вы бы закончили с "nullfoo".)
Обновление: См. fooobar.com/questions/1890/..., который почти идентичен.
Ответ 2
Важным отличием между +=
и concat()
является не производительность, а семантика. concat()
будет принимать только строковый аргумент, но +
(или +=
) ничего не примет. Если операнд без строки является объектом, он будет преобразован в строку, вызвав на нем toString()
; примитив будет преобразован, как если бы он вызывал соответствующий метод в связанном классе-оболочке, например, Integer.toString(theInt)
; и нулевой ссылкой становится строка "null"
.
Собственно, я не знаю, почему concat()
даже существует. Люди видят его в документах API и считают, что это по какой-то причине - производительность является наиболее очевидной причиной. Но это красная сельдь; если производительность действительно вызывает беспокойство, вы должны использовать StringBuilder, как обсуждалось в потоке, с которым связан John. В противном случае +
или +=
гораздо удобнее.
EDIT: Что касается вопроса о "создании объектов в пуле строк", я думаю, вы не понимаете, что такое пул строк. Во время выполнения фактические последовательности символов "str" и "end" будут сохранены в выделенной структуре данных, и везде, где вы видите литералы "str"
и "end"
в исходном коде, байт-код действительно будет содержать ссылки к соответствующим записям в этой структуре данных.
Фактически, пул строк заполняется, когда классы загружаются, а не когда выполняется код, содержащий строковые литералы. Это означает, что каждый из ваших фрагментов создает только один объект: результат конкатенации. (Там также некоторые создания объектов за кулисами, что немного отличается для каждого из методов, но влияние производительности не стоит беспокоиться.)
Ответ 3
Если аргумент concat не является пустой строкой, то
String mystr = "str";
mystr = mystr.concat("end")
также создаст 3 строки.
Дополнительная информация: http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html
Ответ 4
Как я понимаю пул строк это:
У вас, похоже, есть заблуждение относительно этого термина. Нет такой вещи, как "пул строк" - как вы ее используете, похоже, что вы просто имеете в виду весь объект String в куче. Существует пул констант времени выполнения, который содержит, помимо прочего, константы String и String, возвращаемые с String.intern()