> В чем особенности класса String в Kotlin (Kotlin, Android)

Уровень: senior · Роль: mobile · Категория: Технические вопросы

Компании: Aston

Стек: Kotlin, Android

> Пример ответа

Короткий ответ

String в Kotlin - это неизменяемая последовательность символов, представленная классом kotlin.String, который является типом-алиасом для java.lang.String на JVM. Ключевые особенности: неизменяемость, интернирование строковых литералов, отсутствие оператора + для конкатенации в байткоде (используется StringBuilder), поддержка raw strings и string templates. В Kotlin нет отдельного символьного типа для индексации - доступ по индексу возвращает Char, но сравнение строк выполняется через equals, а не == (в Kotlin == - это структурное сравнение).

Подробное объяснение

Основные особенности класса String в Kotlin:

  1. Неизменяемость: объект String нельзя изменить после создания. Любая операция, которая "изменяет" строку, создаёт новый объект. Это обеспечивает потокобезопасность и позволяет безопасно использовать строки как ключи в HashMap.

  2. Интернирование: строковые литералы автоматически помещаются в пул строк (string pool). При сравнении литералов через == Kotlin использует структурное сравнение, поэтому "abc" == "abc" вернёт true даже без явного вызова equals.

  3. String templates: встроенная интерполяция строк через $variable или ${expression}. Это синтаксический сахар, который компилируется в конкатенацию через StringBuilder или String.concat.

  4. Raw strings: тройные кавычки """...""" позволяют создавать многострочные строки без экранирования, сохраняя форматирование.

  5. Отсутствие оператора + для конкатенации в байткоде: компилятор преобразует a + b в StringBuilder.append(), но в Kotlin это неявно, и для производительности в циклах рекомендуется использовать StringBuilder явно.

  6. Сравнение: == в Kotlin - это структурное сравнение (вызов equals), а === - ссылочное. Это отличается от Java, где == сравнивает ссылки.

  7. Null-safety: тип String? явно допускает null, и все операции с nullable-строками требуют safe-call (?.) или elvis-оператор (?:).

  8. Расширения: Kotlin добавляет множество extension-функций: capitalize(), trimIndent(), isNullOrEmpty(), substringAfter(), split() с regex и другие.

На практике

В Android-разработке особенности String критичны:

  • Интерполяция используется повсеместно для построения UI-строк: "Привет, $userName!".
  • Raw strings удобны для SQL-запросов, JSON-шаблонов или многострочных текстов.
  • Неизменяемость важна при работе с многопоточностью (например, в корутинах) - можно безопасно шарить строки между потоками.
  • Производительность: в циклах или при частой конкатенации (например, в адаптерах RecyclerView) нужно использовать StringBuilder, чтобы избежать создания множества промежуточных объектов.
  • Null-safety: при работе с API или SharedPreferences часто приходится обрабатывать nullable-строки через ?. и ?:, чтобы избежать NPE.

Пример кода

fun main() {
    // String templates
    val name = "Анна"
    val age = 28
    println("Имя: $name, возраст: ${age + 1}")

    // Raw strings
    val json = """
        {
            "name": "$name",
            "age": $age
        }
    """.trimIndent()
    println(json)

    // Сравнение
    val a = "hello"
    val b = String(charArrayOf('h', 'e', 'l', 'l', 'o'))
    println(a == b)   // true - структурное сравнение
    println(a === b)  // false - разные объекты

    // Null-safety
    val nullableString: String? = null
    println(nullableString?.length ?: "строка null")

    // Extension functions
    val text = "  Kotlin  "
    println(text.trim().capitalize()) // "Kotlin"

    // Производительность: StringBuilder в цикле
    val sb = StringBuilder()
    for (i in 1..1000) {
        sb.append(i).append(", ")
    }
    println(sb.toString())
}

Как отвечать на собеседовании

Начните с ключевого: неизменяемость и структурное сравнение через ==. Затем перечислите синтаксические особенности - templates, raw strings, null-safety. Упомяните, что на JVM это тот же java.lang.String, но с расширениями. Подчеркните практические следствия: интернирование литералов, необходимость StringBuilder для конкатенации в циклах, безопасность при многопоточности. Если спросят про производительность - упомяните, что компилятор оптимизирует простую конкатенацию, но в сложных сценариях лучше использовать StringBuilder или joinToString(). Не углубляйтесь в детали реализации JVM, если не спрашивают.

Что проверяет интервьюер

Интервьюер оценивает:

  • Понимание фундаментальных свойств: неизменяемость, интернирование, сравнение.
  • Знание синтаксических возможностей Kotlin: templates, raw strings, extension functions.
  • Понимание null-safety и его влияния на работу со строками.
  • Осознание trade-off между удобством и производительностью (конкатенация vs StringBuilder).
  • Умение применять знания в Android-контексте (UI-строки, работа с API).

Типичные ошибки

  • Утверждение, что == в Kotlin сравнивает ссылки, как в Java - это неверно.
  • Игнорирование null-safety: использование String без ? и попытка присвоить null.
  • Чрезмерное использование конкатенации в циклах без StringBuilder - кандидат не учитывает создание промежуточных объектов.
  • Путаница между trim() и trimIndent() - первая убирает пробелы, вторая выравнивает отступы в raw strings.
  • Забывают, что capitalize() deprecated в новых версиях Kotlin (заменён на replaceFirstChar).
  • Утверждение, что String в Kotlin - это отдельный класс, отличный от Java - на JVM это тот же java.lang.String.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью