Есть ли разница между 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()