Строки в Java
Работа с объектами String в Java — создание, конкатенация и обработка строк, а также понимание неизменяемости строк.
String представляет собой последовательность символов и, после int, является типом, с которым вы будете работать чаще всего. Это класс (не примитив), но Java предоставляет ему специальный синтаксис — литералы в двойных кавычках, оператор + для конкатенации — поэтому в использовании он похож на примитив. Самый важный факт о строках: они неизменяемы.
В этой главе рассматривается, как создавать строки, почему неизменяемость важна, как измерять и индексировать строки, как правильно сравнивать их, повседневные методы, конкатенация, многострочные текстовые блоки и форматирование.
Создание строки
Самый простой способ — строковый литерал в двойных кавычках:
String greeting = "Hello, World!";
String empty = "";
String multi = "Line 1\nLine 2"; // \n is a newlineМожно также создать строку с помощью new, хотя для этого редко возникает причина:
String fromLiteral = "Hello";
String fromNew = new String("Hello");new String(...) всегда выделяет новый объект. Литералы помещаются в пул — два литерала с одинаковыми символами являются одним и тем же объектом. Это важно для сравнений с ==, но не во всём остальном; для сравнения содержимого всегда следует использовать .equals().
Строки неизменяемы
После создания String её содержимое никогда не изменяется. Каждый метод, который «изменяет» строку, на самом деле возвращает новую строку:
String s = "hello";
s.toUpperCase();
System.out.println(s); // "hello" — unchanged
s = s.toUpperCase();
System.out.println(s); // "HELLO" — new string assignedНеизменяемость имеет несколько преимуществ:
- Безопасно использовать между потоками — синхронизация не нужна.
- Хеш-код может быть кэширован.
- Строки можно безопасно использовать в качестве ключей в коллекциях.
Компромисс: построение длинной строки в цикле с помощью + создаёт множество промежуточных строк. Для этого используйте StringBuilder (конкатенация строк).
Длина и индексация
length() возвращает количество символов:
String s = "hello";
System.out.println(s.length()); // 5charAt(i) возвращает символ по индексу i (отсчёт с нуля):
System.out.println(s.charAt(0)); // 'h'
System.out.println(s.charAt(4)); // 'o'
// s.charAt(5); // StringIndexOutOfBoundsExceptionПримечание: length() возвращает количество UTF-16 кодовых единиц, а не всегда количество воспринимаемых пользователем символов. Для большинства ASCII и BMP-текста они совпадают, но эмодзи и некоторые нелатинские символы используют суррогатные пары и считаются как 2.
Сравнение строк
Для сравнения содержимого используйте .equals(), а не ==:
String a = new String("hi");
String b = new String("hi");
System.out.println(a == b); // false
System.out.println(a.equals(b)); // trueequalsIgnoreCase игнорирует регистр:
"HELLO".equalsIgnoreCase("hello"); // trueДля упорядочивания используйте compareTo. Он сравнивает строки лексикографически (по коду символа) и возвращает отрицательное число, если первая строка стоит перед второй, 0 при равенстве и положительное число, если первая стоит после:
"apple".compareTo("banana"); // negative (a < b)
"apple".compareTo("apple"); // 0 — equal
"banana".compareTo("apple"); // positive (b > a)Поскольку сравнение производится по коду символа, заглавные буквы (A–Z, коды 65–90) идут раньше строчных (a–z, коды 97–122). Для регистронезависимого упорядочивания используйте compareToIgnoreCase.
Основные операции
Наиболее часто используемые методы с примерами:
String s = " Hello, World! ";
s.length(); // 17
s.trim(); // "Hello, World!" (whitespace removed)
s.strip(); // "Hello, World!" (Unicode-aware, Java 11+)
s.toUpperCase(); // " HELLO, WORLD! "
s.toLowerCase(); // " hello, world! "
s.contains("World"); // true
s.startsWith(" Hello"); // true
s.endsWith("! "); // true
s.indexOf("World"); // 9
s.indexOf("xyz"); // -1
s.replace(",", ";"); // " Hello; World! "
s.substring(2, 7); // "Hello"
s.split(", "); // [" Hello", "World! "]
s.isEmpty(); // false — length() == 0?
s.isBlank(); // false — only whitespace? (Java 11+)Полный справочник см. в методах строк Java.
Конкатенация
Оператор + объединяет строки и при необходимости преобразует другие типы в строку:
String name = "Ada";
int age = 36;
String msg = "Name: " + name + ", Age: " + age;
// "Name: Ada, Age: 36"Внутри цикла предпочтительнее использовать StringBuilder:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
sb.append(i).append(",");
}
String result = sb.toString();Текстовые блоки — многострочные строки
Начиная с Java 15, текстовые блоки позволяют писать многострочные строки без экранирования:
String json = """
{
"name": "Ada",
"age": 36
}
""";Компилятор удаляет общий ведущий пробел из каждой строки, поэтому отступы в исходном коде не попадают в строку.
Форматирование
String.format создаёт строку с заполнителями в стиле printf:
String s = String.format("Name: %s, Age: %d", "Ada", 36);Заполнители те же, что и в System.out.printf — см. вывод в Java.
Демонстрация
Что дальше
Методы строк Java — справочник всех методов, которые вы будете регулярно использовать.