Можно ли объявить поле так, чтобы оно было примитивом после компиляции
Что проверяют
Понимаете ли вы, во что компилируются типы Kotlin на JVM и где появляется упаковка. Вопрос по сути про Kotlin: в Java тип поля и так пишется явно, int или Integer. Следом спрашивают про Int?, дженерики или value class.
Как отвечать
В Kotlin нет отдельных примитивных типов в синтаксисе, решает компилятор. Правила:
val count: Int = 0: ненулевойIntв поле класса компилируется в примитивint. То же дляLong,Double,Booleanи остальных;Int?: всегдаjava.lang.Integer, потому что примитив не может бытьnull;- дженерики:
List<Int>иMap<String, Int>хранят упакованныеInteger, стирание типов не оставляет выбора; - массивы:
IntArrayэтоint[], аArray<Int>этоInteger[]; const val: константа времени компиляции, подставляется в места использования;lateinit: для примитивных типов запрещён, компилятор выдаст ошибку. Нужно значение по умолчанию,Delegates.notNull()илиInt?;- делегаты:
val x: Int by lazy { ... }хранит объектLazy, и значение внутри упаковано.
Отдельно стоит упомянуть @JvmInline value class UserId(val raw: Int): в сигнатурах и полях это просто int, но при использовании как nullable, как параметра дженерика или через интерфейс значение упаковывается.
Для Android это важно в горячем коде: в onDraw, адаптерах списков и анимациях упаковка создаёт мусор, и сборщик отнимает кадры. Отсюда SparseIntArray вместо HashMap<Int, Int>, а в Compose mutableIntStateOf вместо mutableStateOf<Int>. Проверить результат можно через Show Kotlin Bytecode в Android Studio.
Где спотыкаются
Говорят, что в Java поля по умолчанию ссылочные или что final делает поле примитивом. Способ хранения задаёт сам тип, final на него не влияет.
Считают Int? примитивом, «потому что это Int». На каждом присвоении создаётся или берётся из кеша Integer, и сравнение через === за пределами кеша от -128 до 127 может дать false.
Пишут lateinit var id: Int и удивляются ошибке компиляции, либо ради отложенной инициализации меняют тип на Int? и получают упаковку плюс проверки на null по всему коду.