String.concat: примеры (JAVA)

Метод concat класса String в Java: разбор и примеры
Раздел: Строки (String) - базовые операции
String.concat(String str): String

Обзор метода String.concat

В Java метод String.concat служит для объединения двух строк. Официальная сигнатура:

public String concat(String str)

Поведение и назначение:

  • Если аргумент str равен null, генерируется NullPointerException.
  • Если str.length() == 0, метод возвращает исходную строку (это тот же объект).
  • Если текущая строка пуста (длина 0), возвращается сама str (то есть ссылка на переданный объект).
  • В остальных случаях возвращается новая строка, содержащая последовательность символов исходной строки, за которой следует последовательность символов аргумента.

Возвращаемое значение: новая строка или одна из исходных ссылок в случаях с пустой строкой. Метод не изменяет исходные объекты, так как String в Java неизменяемый тип.

Сложность по времени пропорциональна сумме длин объединяемых строк. Для многократного конкатенирования рекомендуется рассмотреть альтернативы (см. разделы ниже).

Замечания о реализации: внутреннее представление строк изменилось в Java 9 (компактные строки), но семантика concat осталась прежней. В разных версиях возможны оптимизации при возвращении ссылок при пустых аргументах.

Короткие примеры использования

Несколько простых сценариев с кодом и результатом.

Обычное объединение:

String a = "Hello";
String b = " World";
String c = a.concat(b);
System.out.println(c);
Hello World

Пустая вторая строка возвращает исходную ссылку:

String a = "Hi";
String b = "";
String c = a.concat(b);
System.out.println(c == a); // сравнение ссылок
true

Пустая первая строка возвращает ссылку на аргумент:

String a = "";
String b = "nonempty";
String c = a.concat(b);
System.out.println(c == b);
true

Передача null вызывает исключение:

String a = "x";
String b = null;
String c = a.concat(b);
// бросит NullPointerException
Exception in thread "main" java.lang.NullPointerException
	at java.lang.String.concat(String.java:...)
	... 

Альтернативы в Java и их отличия

  • Оператор + - синтаксический сахар, который при компиляции ряда литералов может быть оптимизирован; при динамическом объединении в цикле ведет к созданию временных объектов.
  • StringBuilder.append - предпочтителен при множественных операциях конкатенации в циклах, потому что минимизирует выделения памяти и копирования.
  • StringBuffer.append - похож на StringBuilder, но синхронизирован; уместен в многопоточных сценариях, где требуется потокобезопасность.
  • String.join - удобен для объединения коллекций/массива с разделителем; эффективен и читабелен для множественных элементов.
  • Collectors.joining (Streams) - применяется при работе со стримами, более выразителен и избегает явных циклов.
  • String.format - для форматированного объединения с шаблоном; удобен при необходимости вставки форматов и локализации.

Вариант использования выбирается в зависимости от частоты операций и требований к производительности и потокобезопасности.

Сравнение с похожими функциями в других языках

Краткие отличия и примеры для распространённых языков.

  • JavaScript: метод concat и оператор +. Конкатенация с null даёт строку "null" при использовании +.
let a = "Hi";
let b = null;
console.log(a + b);
console.log(a.concat(" ", "JS"));
Hinull
Hi JS
  • Python: оператор + для строк; конкатенация с None вызовет TypeError. Более эффективно использовать str.join для списка.
a = "Hi"
b = None
# a + b  # TypeError
print(" ".join(["a","b"]))
a b
  • PHP: оператор .. При конкатенации с null обычно получается пустая строка для null-переменной.
$a = "Hi";
$b = null;
echo $a . $b;
Hi
  • C#: String.Concat и оператор +. В C# null трактуется как пустая строка при использовании String.Concat, то есть не бросает исключение.
string a = "Hi";
string b = null;
Console.WriteLine(string.Concat(a, b));
Hi
  • Go: оператор + для строк. Значение nil для строк в Go не существует, нулевого указателя для string нет; пустая строка используется по умолчанию.
a := "Hi"
b := ""
fmt.Println(a + b)
Hi
  • Kotlin: оператор + и функция plus. При null требуется безопасный вызов или явная проверка.
val a: String = "Hi"
val b: String? = null
println(a + b) // "Hinull" если b неявно приведен
println(a.plus(b ?: ""))
Hinull
Hi
  • Lua: оператор .. для конкатенации; конкатенация с nil вызывает ошибку.
a = "Hi"
b = nil
-- print(a .. b) -- error
print(a .. " Lua")
Hi Lua
  • SQL: в большинстве диалектов используется оператор || или функция CONCAT. Обработка NULL зависит от СУБД (часто NULL в результате делает весь результат NULL, но есть функции COALESCE/IFNULL для обхода).
-- в PostgreSQL
SELECT 'a' || NULL || 'b';
-- в MySQL
SELECT CONCAT('a', NULL, 'b');
-- PostgreSQL: NULL
-- MySQL: NULL (CONCAT возвращает NULL при любом NULL аргументе)

Ключевое отличие Java: String.concat бросает NullPointerException при null-аргументе, тогда как в других языках поведение варьируется от преобразования в "null" до игнорирования или генерации ошибки.

Типичные ошибки и их проявления

Несколько распространённых проблем при использовании String.concat.

1) NullPointerException при передаче null:

String s = "a";
s.concat(null);
Exception in thread "main" java.lang.NullPointerException
	at java.lang.String.concat(String.java:...)
	... 

2) Ожидание изменения исходной строки (ошибочное предположение о мутабельности):

String s = "a";
s.concat("b");
System.out.println(s);
a

Пояснение: метод возвращает новую строку, исходный объект остаётся прежним.

3) Низкая производительность при конкатенировании в цикле:

String res = "";
for (String part : parts) {
    res = res.concat(part);
}
Для большого числа элементов приводит к множественным аллокациям и копированию; рекомендуется StringBuilder.

4) Неправильные ожидания при работе с кодировками и многобайтовыми символами: метод оперирует символами (UTF-16 code units), поэтому при работе с суррогатными парами и индексами нужно учитывать специфику.

Изменения в реализации в последних версиях

Семантика метода String.concat в Java не претерпела изменений: сигнатура и поведение остались совместимыми. Основные изменения касаются внутренней реализации строк:

  • В Java 9 введено компактное представление строк (byte[] + coder), что повлияло на внутреннюю реализацию операций с символами и памятью, но не изменило внешнее поведение concat.
  • В последующих релизах могли появиться оптимизации аллокаций и копирования, однако API и исключения остались прежними.

Расширенные и редкие сценарии применения

Несколько продвинутых примеров с объяснениями.

1) Безопасная конкатенация, допускающая null, с использованием Objects.toString:

Пример java
String a = "start";
String b = null;
String result = a.concat(Objects.toString(b, ""));
System.out.println(result);
start

Пояснение: Objects.toString(b, "") превращает null в пустую строку и предотвращает NullPointerException.

2) Использование concat при обработке substrings и сохранении ссылок (проверка оптимизаций):

Пример java
String a = "";
String b = "payload";
String c = a.concat(b);
System.out.println(c == b);
true

Пояснение: при пустой левой строке возвращается ссылка на правую. Это может использоваться для экономии памяти при комбинации с пустыми фрагментами.

3) Неподходящий вариант при сборке больших строк: сравнение с StringBuilder:

Пример java
// Плохо: много аллокаций
String s = "";
for (int i = 0; i < 10000; i++) s = s.concat("x");

// Лучше
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) sb.append('x');
String good = sb.toString();
Первый вариант медленный и потребляет больше памяти; второй вариант предпочтительнее.

4) Использование в Stream.reduce: неэффективность и альтернатива:

Пример java
List parts = Arrays.asList("a","b","c");
String reduced = parts.stream().reduce("", String::concat);
System.out.println(reduced);

// Лучше
String joined = parts.stream().collect(Collectors.joining());
System.out.println(joined);
abc
abc

Пояснение: reduce с конкатенацией создаёт множество временных строк; Collectors.joining использует оптимизации.

5) Конкатенация больших массивов строк с предварительным вычислением итоговой длины (редко используемый ручной оптимизируемый вариант):

Пример java
String[] arr = {"one","two","three"};
int total = 0;
for (String s : arr) total += s.length();
StringBuilder sb = new StringBuilder(total);
for (String s : arr) sb.append(s);
String result = sb.toString();
System.out.println(result);
onetwothree

Пояснение: предварительное выделение места в StringBuilder минимизирует дополнительные аллокации.

6) Комбинация с интернированием и экономией памяти (редкий кейс):

Пример java
String a = "Hello";
String b = " World";
String c = a.concat(b).intern();
System.out.println(c == ("Hello World"));
true

Пояснение: intern() может быть использован для хранения единственного экземпляра строки в пуле, но использование intern имеет побочные эффекты на работу GC и память и требует осторожности.

джава String.concat function comments

En
String.concat Concatenates the specified string to the end of this string