String-Methoden – Vollständige Anleitung in Kotlin: Eine ausführliche Anleitung
Что это такое и зачем? (аналогия из реальной жизни)
Представьте, что вы получили длинное письмо от друга. Что вы можете с ним сделать? Вы можете:
- Посчитать, сколько в нём слов
- Найти, встречается ли в нём слово «привет»
- Заменить одно слово на другое
- Разделить письмо на отдельные предложения
- Убрать лишние пробелы в начале и конце
- Сделать все буквы заглавными или маленькими
- Проверить, не пустое ли письмо
В программировании строки — это точно такие же «письма», только хранятся они в памяти компьютера. И для работы с ними существуют специальные инструменты — методы строк. Это как набор ножниц, клея, линеек и маркеров, которые помогают вам обрабатывать текст.
Важно: Строки в Kotlin — это неизменяемые (immutable) объекты. Это значит, что когда вы вызываете метод, вы не меняете исходную строку, а создаёте новую. Представьте, что вы делаете ксерокопию письма и работаете уже с копией.
Зачем это нужно? Представьте, что вы пишете программу для регистрации пользователей. Вам нужно:
- Убрать лишние пробелы из имени (чтобы «Анна » превратилось в «Анна»)
- Проверить, что email содержит символ «@»
- Сделать первую букву имени заглавной
- Заменить в тексте все нецензурные слова на звёздочки
Без методов строк вам пришлось бы писать десятки строк кода вручную. С ними — одна строчка.
Теория: как это работает изнутри
Давайте заглянем «под капот» и поймём, как устроены строки в Kotlin.
Строка — это массив символов
Внутри компьютера строка — это просто последовательность символов (букв, цифр, знаков препинания), расположенных друг за другом. Каждый символ имеет свой номер — индекс. Первый символ имеет индекс 0, второй — 1, и так далее.
Например, строка «Кот» внутри выглядит так:
// Индексы: 0 1 2
// Символы: 'К' 'о' 'т'
val word = "Кот"
println(word[0]) // Выведет: К
println(word[1]) // Выведет: о
println(word[2]) // Выведет: т
Неизменяемость (иммутабельность)
Когда вы вызываете метод toUpperCase(), Kotlin не меняет исходную строку. Вместо этого он создаёт новую строку в памяти, применяет к ней изменения, и возвращает её вам. Исходная строка остаётся нетронутой.
val original = "Привет"
val changed = original.toUpperCase() // Создаётся НОВАЯ строка "ПРИВЕТ"
println(original) // "Привет" — исходная не изменилась!
println(changed) // "ПРИВЕТ" — новая строка
Почему это важно? Представьте, что у вас есть важный документ. Вы делаете его копию и рисуете на копии. Оригинал остаётся в сохранности. Так и со строками — вы всегда можете вернуться к исходному значению.
Строковый пул (String Pool)
Kotlin (как и Java) использует специальную область памяти — строковый пул. Когда вы создаёте строку с помощью кавычек, Kotlin сначала проверяет: а нет ли уже такой строки в пуле? Если есть — он просто даёт вам ссылку на неё. Это экономит память.
val a = "Привет"
val b = "Привет"
// a и b ссылаются на ОДИН И ТОТ ЖЕ объект в памяти!
println(a === b) // true — это одна и та же ссылка
Кодировка: как хранятся символы
В Kotlin строки хранятся в кодировке UTF-16. Это значит, что каждый символ занимает 2 байта (или 4 для редких символов). Благодаря этому вы можете работать с любыми языками мира: русским, китайским, арабским — без проблем.
Синтаксис в Kotlin: все формы и варианты
Давайте разберём все основные методы строк. Я сгруппировал их по категориям, чтобы было легче запомнить.
1. Проверка и сравнение
| Метод | Что делает | Пример | Результат |
|---|---|---|---|
isEmpty() |
Проверяет, пустая ли строка (длина = 0) | "".isEmpty() |
true |
isNotEmpty() |
Проверяет, не пустая ли строка | "Кот".isNotEmpty() |
true |
isBlank() |
Проверяет, пустая ли строка или состоит только из пробелов | " ".isBlank() |
true |
equals(other) |
Сравнивает строки по содержимому | "Кот".equals("Кот") |
true |
== |
То же самое, что equals (в Kotlin) | "Кот" == "Кот" |
true |
2. Поиск и проверка содержимого
| Метод | Что делает | Пример | Результат |
|---|---|---|---|
contains("текст") |
Проверяет, содержит ли строка указанный текст | "Привет".contains("иве") |
true |
startsWith("Пре") |
Проверяет, начинается ли строка с указанного текста | "Прекрасный".startsWith("Пре") |
true |
endsWith("конец") |
Проверяет, заканчивается ли строка указанным текстом | "Это конец".endsWith("конец") |
true |
indexOf("символ") |
Находит индекс первого вхождения текста (или -1, если не найдено) | "Котёнок".indexOf("тё") |
2 |
lastIndexOf("о") |
Находит индекс последнего вхождения | "Молоко".lastIndexOf("о") |
4 |
3. Изменение регистра
| Метод | Что делает | Пример | Результат |
|---|---|---|---|
toUpperCase() |
Превращает все буквы в заглавные | "кот".toUpperCase() |
"КОТ" |
toLowerCase() |
Превращает все буквы в строчные | "КОТ".toLowerCase() |
"кот" |
capitalize() |
Делает первую букву заглавной (устарел, но работает) | "кот".capitalize() |
"Кот" |
decapitalize() |
Делает первую букву строчной | "Кот".decapitalize() |
"кот" |
4. Обрезка и удаление
| Метод | Что делает | Пример | Результат |
|---|---|---|---|
trim() |
Убирает пробелы в начале и конце | " Кот ".trim() |
"Кот" |
trimStart() |
Убирает пробелы только в начале | " Кот".trimStart() |
"Кот" |
trimEnd() |
Убирает пробелы только в конце | "Кот ".trimEnd() |
"Кот" |
removePrefix("Пре") |
Удаляет указанное начало, если оно есть | "Прекрасный".removePrefix("Пре") |
"красный" |
removeSuffix("конец") |
Удаляет указанный конец, если он есть | "Это конец".removeSuffix(" конец") |
"Это" |
5. Замена и разделение
| Метод | Что делает | Пример | Результат |
|---|---|---|---|
replace("старое", "новое") |
Заменяет все вхождения одного текста на другой | "кот кот".replace("кот", "пёс") |
"пёс пёс" |
replaceFirst("кот", "пёс") |
Заменяет только первое вхождение | "кот кот".replaceFirst("кот", "пёс") |
"пёс кот" |
split("разделитель") |
Разделяет строку на части по указанному разделителю | "яблоко,груша,банан".split(",") |
["яблоко", "груша", "банан"] |
6. Извлечение части строки
| Метод | Что делает | Пример | Результат |
|---|---|---|---|
substring(начало, конец) |
Извлекает часть строки от индекса «начало» до «конец» (не включая конец) | "Привет".substring(0, 4) |
"Прив" |
take(3) |
Берёт первые N символов | "Привет".take(3) |
"При" |
takeLast(3) |
Берёт последние N символов | "Привет".takeLast(3) |
"вет" |
drop(3) |
Удаляет первые N символов, возвращает остаток | "Привет".drop(3) |
"вет" |
dropLast(3) |
Удаляет последние N символов | "Привет".dropLast(3) |
"При" |
7. Дополнительные полезные методы
| Метод | Что делает | Пример | Результат |
|---|---|---|---|
length |
Возвращает длину строки (количество символов) | "Кот".length |
3 |
reversed() |
Переворачивает строку задом наперёд | "Кот".reversed() |
"тоК" |
repeat(3) |
Повторяет строку указанное количество раз | "Ха".repeat(3) |
"ХаХаХа" |
padStart(10, '*') |
Дополняет строку слева до указанной длины | "Кот".padStart(10, '*') |
"*******Кот" |
padEnd(10, '*') |
Дополняет строку справа до указанной длины | "Кот".padEnd(10, '*') |
"Кот*******" |
Примеры кода — от простого к сложному
Пример 1: Приветствие пользователя (базовые методы)
fun main() {
// Представьте, что пользователь ввёл своё имя с лишними пробелами
val userInput = " анна "
// Убираем пробелы в начале и конце
val cleanedName = userInput.trim()
// Делаем первую букву заглавной, остальные — маленькими
val formattedName = cleanedName.capitalize()
// Выводим приветствие
println("Привет, $formattedName!") // Выведет: Привет, Анна!
// Проверяем, что исходная строка не изменилась
println("Исходная строка: '$userInput'") // Выведет: ' анна '
}
Пример 2: Проверка пароля (методы проверки)
fun main() {
val password = "Secret123"
// Проверяем длину пароля
if (password.length < 8) {
println("Пароль слишком короткий!")
}
// Проверяем, содержит ли пароль цифры
val hasDigit = password.any { it.isDigit() }
if (!hasDigit) {
println("Пароль должен содержать хотя бы одну цифру!")
}
// Проверяем, содержит ли пароль заглавные буквы
val hasUpperCase = password.any { it.isUpperCase() }
if (!hasUpperCase) {
println("Пароль должен содержать хотя бы одну заглавную букву!")
}
// Если все проверки пройдены
if (password.length >= 8 && hasDigit && hasUpperCase) {
println("Пароль надёжный!")
}
}
Пример 3: Обработка email-адреса
fun main() {
val email = " User@Example.COM "
// 1. Убираем пробелы
val trimmed = email.trim()
// 2. Проверяем, есть ли символ '@'
if (!trimmed.contains("@")) {
println("Ошибка: email должен содержать @")
return
}
// 3. Разделяем email на имя пользователя и домен
val parts = trimmed.split("@")
val username = parts[0]
val domain = parts[1]
// 4. Приводим домен к нижнему регистру (обычно так делают)
val normalizedDomain = domain.toLowerCase()
// 5. Собираем обратно
val normalizedEmail = "$username@$normalizedDomain"
println("Исходный email: $email")
println("Нормализованный: $normalizedEmail")
// Выведет: Нормализованный: User@example.com
}
Пример 4: Цензура текста (замена слов)
fun main() {
val badWords = listOf("дурак", "идиот", "плохой")
val text = "Ты дурак, если думаешь, что это плохой фильм!"
var censoredText = text
// Проходим по всем плохим словам и заменяем их на звёздочки
for (word in badWords) {
// Создаём строку из звёздочек той же длины
val stars = "*".repeat(word.length)
censoredText = censoredText.replace(word, stars)
}
println("Исходный текст: $text")
println("После цензуры: $censoredText")
// Выведет: После цензуры: Ты *****, если думаешь, что это ****** фильм!
}
Пример 5: Анализ текста (статистика)
fun main() {
val text = "Кот и собака дружат. Кот любит молоко. Собака любит кости."
// 1. Разделяем текст на слова
val words = text.split(" ", ".", "!") // Разделяем по пробелам и знакам препинания
println("Всего слов: ${words.size}")
// 2. Считаем, сколько раз встречается слово "Кот"
val catCount = words.count { it == "Кот" || it == "кот" }
println("Слово 'Кот' встречается $catCount раз(а)")
// 3. Находим самое длинное слово
val longestWord = words.maxByOrNull { it.length }
println("Самое длинное слово: '$longestWord' (${longestWord?.length} букв)")
// 4. Переворачиваем каждое слово
val reversedWords = words.map { it.reversed() }
println("Слова задом наперёд: $reversedWords")
}
Пример 6: Форматирование номера телефона
fun main() {
// Представьте, что пользователь ввёл номер телефона без форматирования
val rawPhone = "1234567890"
// Проверяем, что номер состоит только из цифр
if (!rawPhone.all { it.isDigit() }) {
println("Ошибка: номер должен содержать только цифры!")
return
}
// Проверяем длину
if (rawPhone.length != 10) {
println("Ошибка: номер должен содержать 10 цифр!")
return
}
// Форматируем: (123) 456-7890
val areaCode = rawPhone.take(3)
val firstPart = rawPhone.substring(3, 6)
val secondPart = rawPhone.takeLast(4)
val formattedPhone = "($areaCode) $firstPart-$secondPart"
println("Исходный номер: $rawPhone")
println("Отформатированный: $formattedPhone")
// Выведет: Отформатированный: (123) 456-7890
}
Пример 7: Генератор «лесенки» из текста
fun main() {
val word = "Кот"
// Создаём «лесенку»: сначала одна буква, потом две, потом три...
println("Строим лесенку из слова '$word':")
for (i in 1..word.length) {
// Берём первые i символов
val part = word.take(i)
// Дополняем справа точками до длины исходного слова
val padded = part.padEnd(word.length, '.')
println(padded)
}
// Выведет:
// К..
// Ко.
// Кот
}
Пример 8: Проверка, является ли строка палиндромом
fun main() {
fun isPalindrome(text: String): Boolean {
// Убираем пробелы и приводим к нижнему регистру
val cleaned = text.replace(" ", "").toLowerCase()
// Сравниваем с перевёрнутой версией
return cleaned == cleaned.reversed()
}
// Тестируем
val test1 = "А роза упала на лапу Азора"
val test2 = "Привет"
println("'$test1' — палиндром? ${isPalindrome(test1)}") // true
println("'$test2' — палиндром? ${isPalindrome(test2)}") // false
}
Сравнение с Python: чем похоже и чем отличается
Если вы уже знакомы с Python, вам будет легче изучать Kotlin. Давайте сравним основные методы:
| Операция | Kotlin | Python | Примечание |
|---|---|---|---|
| Длина строки | "кот".length |
len("кот") |
В Kotlin это свойство, в Python — функция |
| Верхний регистр | "кот".toUpperCase() |
"кот".upper() |
Разные названия методов |
| Нижний регистр | "КОТ".toLowerCase() |
"КОТ".lower() |
Разные названия |
| Удаление пробелов | " кот ".trim() |
" кот ".strip() |
Разные названия |
| Разделение | "a,b".split(",") |
"a,b".split(",") |
Одинаково! |
| Замена | "кот".replace("к", "п") |
"кот".replace("к", "п") |
Одинаково! |
| Проверка начала | "кот".startsWith("к") |
"кот".startswith("к") |
Разный регистр буквы 'w' |
| Проверка конца | "кот".endsWith("т") |
"кот".endswith("т") |
Разный регистр буквы 'w' |
| Поиск подстроки | "кот".indexOf("о") |
"кот".index("о") |
В Python — index, в Kotlin — indexOf |
| Извлечение части | "кот".substring(0, 2) |
"кот"[0:2] |
В Python — срезы, в Kotlin — метод |
| Повторение строки | "Ха".repeat(3) |
"Ха" * 3 |
В Python — оператор, в Kotlin — метод |
Главное отличие: В Python строки тоже неизменяемы, но синтаксис более лаконичный (особенно срезы). Kotlin более строгий в типах, но предлагает больше встроенных методов для работы со строками.
Типичные ошибки и подводные камни
Ошибка 1: Забываем, что строки неизменяемы
fun main() {
var text = "Привет"
text.toUpperCase() // ОШИБКА: результат не сохранён!
println(text) // Выведет: "Привет" — строка не изменилась!
// Правильно:
text = text.toUpperCase()
println(text) // "ПРИВЕТ"
}
Ошибка 2: Путаем isEmpty() и isBlank()
fun main() {
val text = " "
println(text.isEmpty()) // false — строка не пустая, в ней есть пробелы
println(text.isBlank()) // true — строка состоит только из пробелов
// Если вам нужно проверить, что пользователь что-то ввёл,
// используйте isBlank(), а не isEmpty()!
}
Ошибка 3: Выход за границы строки
fun main() {
val text = "Кот"
// println(text[5]) // ОШИБКА! Индекс 5 не существует (максимум 2)
// Безопасный способ — использовать getOrNull
println(text.getOrNull(5)) // null — ошибки нет
println(text.getOrNull(5) ?: "Символа нет") // "Символа нет"
}
Ошибка 4: Сравнение строк через === вместо ==
fun main() {
val a = "Привет"
val b = String("Привет".toCharArray()) // Создаём новую строку
println(a == b) // true — сравнивает содержимое
println(a === b) // false — сравнивает ссылки (разные объекты)
// ВСЕГДА используйте == для сравнения строк!
}
Ошибка 5: Забываем про регистр при поиске
fun main() {
val text = "Кот и собака"
// Поиск без учёта регистра
println(text.contains("кот")) // false — потому что "Кот" с большой буквы
// Правильно:
println(text.toLowerCase().contains("кот")) // true
}
Ошибка 6: Неправильное использование split
fun main() {
val text = "яблоко,груша,банан"
// Разделяем по запятой
val fruits = text.split(",")
println(fruits) // [яблоко, груша, банан]
// ОШИБКА: если разделитель не найден, вернётся список с одним элементом
val result = text.split(";")
println(result) // [яблоко,груша,банан] — весь текст как один элемент
}
Лучшие практики и советы профессионалов
1. Используйте цепочки методов (method chaining)
Методы можно вызывать друг за другом. Это делает код компактным и читаемым:
// Плохо: много временных переменных
val input = " ПРИВЕТ "
val trimmed = input.trim()
val lower = trimmed.toLowerCase()
val capitalized = lower.capitalize()
// Хорошо: цепочка методов
val result = input.trim().toLowerCase().capitalize()
println(result) // "Привет"
2. Используйте строковые шаблоны вместо конкатенации
← Vorherige
Dateiarbeit in Kotlin: Eine ausführliche Anleitung
Weiter →
Methoden für Arrays und Sammlungen in Kotlin: Eine