> В чем разница между Int и Int? в Kotlin и когда Int рассматривается как объект, а когда как примитив (Kotlin, Android)

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

Компании: ЛеруаМерлен

Стек: Kotlin, Android

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

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

Int - это тип данных в Kotlin, который на уровне JVM компилируется в примитивный int, когда это возможно, и в объект java.lang.Integer, когда требуется nullable или использование в generics. Разница проявляется в производительности и поведении: примитив не может быть null и не имеет методов, а объект - полноценный экземпляр класса с дополнительными накладными расходами.

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

В Kotlin Int - это единый тип с точки зрения языка, но под капотом компилятор принимает решение о представлении:

  • Примитив (int) - используется по умолчанию для локальных переменных, параметров функций, полей классов, если значение не nullable и не участвует в generics. Это быстрый и компактный вариант без overhead.
  • Объект (Integer) - используется в трёх случаях:
    1. Когда переменная объявлена как nullable: Int?
    2. Когда тип используется как аргумент типа в generics: List<Int>
    3. Когда происходит приведение к Any или Any?

Компилятор автоматически выполняет boxing (упаковку в объект) и unboxing (распаковку обратно в примитив) при необходимости. Это происходит неявно, но влияет на производительность в циклах и горячих путях.

Важно: на других платформах (Kotlin/Native, Kotlin/JS) представление может отличаться, но для Android и JVM описание выше актуально.

На практике

Для Android-разработки различие важно в следующих сценариях:

  • Производительность: в больших циклах или при работе с коллекциями примитивов лучше использовать специализированные коллекции из kotlin.collections (например, IntArray вместо List<Int>), чтобы избежать boxing.
  • Nullable: если поле может быть null, оно всегда будет объектом - это нормально, но стоит помнить о дополнительной памяти.
  • Generics: List<Int> хранит объекты, а IntArray - примитивы. Выбор зависит от задачи: IntArray быстрее, но менее гибкий.
  • Сравнение: == сравнивает значения, а === - ссылки. Для nullable Int оператор == корректно обрабатывает null.

Пример кода

fun main() {
    // Примитив: не nullable, не в generics
    val a: Int = 42
    val b: Int = 42
    println(a == b) // true, сравнение значений
    println(a === b) // true, так как оба примитивы (компилятор оптимизирует)

    // Объект: nullable
    val c: Int? = 42
    val d: Int? = 42
    println(c == d) // true, сравнение значений
    println(c === d) // false, разные объекты Integer

    // Объект: в generics
    val list: List<Int> = listOf(1, 2, 3)
    val first = list[0] // boxing при извлечении

    // Примитивный массив - без boxing
    val intArray = intArrayOf(1, 2, 3)
    val firstPrimitive = intArray[0] // примитив int
}

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

Начните с ключевого тезиса: Int - это один тип в Kotlin, но компилятор выбирает представление. Затем перечислите три случая, когда используется объект: nullable, generics, приведение к Any. Упомяните автоматический boxing/unboxing и его влияние на производительность. Если спросят про ===, объясните разницу между сравнением значений и ссылок. Хорошо показать понимание на примере IntArray vs List<Int>.

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

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

  • понимание того, как Kotlin работает на JVM
  • знание trade-off между примитивами и объектами
  • способность объяснить неявное поведение компилятора
  • практическое понимание производительности в Android-контексте

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

  • Утверждение, что Int всегда примитив или всегда объект - это неверно.
  • Игнорирование случая с Any - приведение Int к Any всегда создаёт объект.
  • Путаница между == и === для nullable типов.
  • Рекомендация всегда использовать IntArray вместо List<Int> без учёта контекста - это не всегда оправдано.

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

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