Работа со строковыми данными
String и неизменяемость
String — неизменяемая последовательность кодовых единиц UTF-16. Любая операция, которая выглядит как изменение, возвращает новую строку:
String status = " new ";
String normalized = status.trim().toUpperCase(Locale.ROOT);
System.out.println(status); // " new "
System.out.println(normalized); // "NEW"Неизменяемость делает строки безопасными ключами хеш-таблиц, позволяет переиспользовать литералы и упрощает совместный доступ между потоками.
Пул строк
Литералы интернируются:
String first = "java";
String second = "java";
String third = new String("java");
first == second; // true для этих литералов
first == third; // false
first.equals(third); // true== сравнивает ссылки и не подходит для содержимого. equals сравнивает последовательность символов. intern() вручную возвращает каноническую строку из пула, но это редко нужно прикладному коду и не заменяет equals.
Конкатенация
Константные выражения компилятор может склеить заранее:
String header = "Java" + "Notes";В цикле выражение result = result + part создаёт множество промежуточных строк. Для накопления используют StringBuilder:
StringBuilder builder = new StringBuilder();
for (String part : parts) {
builder.append(part).append('\n');
}
String result = builder.toString();StringBuilder не потокобезопасен. StringBuffer синхронизирован, но обычно совместное изменение буфера лучше вообще не разделять между потоками.
Для соединения готовой коллекции есть String.join и Collectors.joining.
Unicode
length() возвращает число char, а не обязательно число отображаемых символов. Символ вне Basic Multilingual Plane занимает surrogate pair:
String text = "A😀";
int units = text.length(); // 3
int points = text.codePointCount(0, text.length()); // 2Даже code point не всегда равен видимой графеме: комбинируемые знаки могут отображаться вместе. Для обычной бизнес-валидации важно заранее определить, что именно значит «длина».
Сравнение и порядок
equals— точное сравнение содержимого.equalsIgnoreCase— регистронезависимое сравнение с ограничениями Unicode/локали.compareTo— лексикографический порядок по кодовым единицам.- Для пользовательской сортировки по языковым правилам нужен
Collator, а не простойcompareTo.
Nullable-строки можно сравнивать через Objects.equals.
Проверка пустоты
String empty = "";
String spaces = " ";
empty.isEmpty(); // true
spaces.isBlank(); // trueisBlank учитывает пробельные символы, isEmpty — только нулевую длину. Оба метода требуют ненулевой ссылки.
Ловушки
- Сравнивать строки через
==. - Забывать присвоить результат
trim,replace,toLowerCase. - Склеивать строку оператором
+внутри большого цикла. - Считать
length()числом пользовательских символов. - Вызывать метод на nullable-строке.
- Нормализовать идентификаторы через
toLowerCase()без явной локали; для машинных токенов обычно используютLocale.ROOT.
Вопросы на собеседовании
- Почему
Stringнеизменяем? - Чем
==отличается отequalsдля строк? - Что такое пул строк?
- Когда нужен
StringBuilder? - Почему
String.length()не всегда равен числу символов на экране? - Чем
isEmptyотличается отisBlank?
Связанные заметки
Методы класса String · Класс Object · Equals и hashCode · Класс Collectors и его методы · Immutable классы и данные