String — текст
String — это текст в двойных кавычках: "Артур". Внутри — цепочка символов, у каждого свой номер (индекс), считаем с нуля.
"Артур".length() → 5 · .charAt(0) → 'А' · .substring(1,3) → "рт"Две ловушки на старте
1. Строки неизменяемы. Любой метод не меняет строку, а возвращает новую. Поэтому результат надо присвоить:
String s = "hi";
s.toUpperCase(); // ❌ результат потерян — s всё ещё "hi"
s = s.toUpperCase(); // ✅ теперь s = "HI"
2. Сравнивай через equals, а не ==. equals сравнивает содержимое, == — ссылки (один ли это объект).
name.equals("Артур") // ✅ сравнить текст
name == "Артур" // ❌ так нельзя
Частые методы
| Метод | Что делает | Результат |
|---|---|---|
s.length() | длина | int |
s.toUpperCase() | в верхний регистр | String |
s.charAt(0) | символ по индексу | char |
s.substring(1, 3) | вырезать часть | String |
s.contains("рт") | содержит ли | boolean |
s.equals("...") | сравнить текст | boolean |
s.trim() | убрать пробелы по краям | String |
Копнуть глубже
Почему строки вообще нельзя менять? Четыре причины:
- Безопасность. Строки — это пути к файлам, URL, параметры подключения. Будь они изменяемы, значение можно было бы подменить уже после проверки.
- Экономия памяти (String Pool). Раз строку нельзя менять, одинаковые литералы можно безопасно переиспользовать — об этом ниже.
- Кэш
hashCode. Хеш считается один раз и запоминается (строка же не меняется) — это ускоряет строки как ключи вHashMap. - Потокобезопасность. Неизменяемый объект можно шарить между потоками без блокировок.
Зачем отдельный String Pool? Это область памяти, где Java хранит строковые литералы. Все одинаковые литералы ("Hi" в разных местах программы) ссылаются на один объект в пуле — огромная экономия памяти. Это работает только потому, что строки неизменяемы: иначе изменение одной строки сломало бы все ссылки на неё.
StringBuilder. Из-за неизменяемости каждый s += x создаёт новую строку. В цикле это гора мусора. Когда склеиваешь много — бери StringBuilder: он меняет один буфер на месте.
Под капотом
Как строки ссылаются и где лежат:
Литералы "Hi" берутся из пула (один объект на всех). new String("Hi") принудительно создаёт отдельный объект в куче. Поэтому для строк всегда equals, а не ==.
Immutable + HashMap — зачем это. Строки чаще всего и используют как ключи в HashMap. Map раскладывает ключи по hashCode. Так как строка неизменяема:
- её
hashCodeникогда не меняется (и кэшируется) → ключ всегда находится в своей «корзине»; - если бы строку-ключ можно было изменить после вставки, её
hashCodeстал бы другим → запись потерялась бы, Map искал бы её не там.
Поэтому неизменяемость — это то, что делает строку надёжным ключом.
• что такое String Pool и зачем он (если дошёл до 2-го слоя);
• почему неизменяемость делает строку хорошим ключом HashMap (если дошёл до 3-го слоя).