> Как проверить тип параметра в обобщённом методе Kotlin (Kotlin, Android)
Уровень: senior · Роль: mobile · Категория: Технические вопросы
Компании: Aston
Стек: Kotlin, Android
> Пример ответа
Короткий ответ
В Kotlin тип параметра обобщённого метода проверяется через is-проверку, но с ограничением: из-за type erasure на JVM нельзя напрямую проверить конкретный тип аргумента внутри generic-метода. Решение - использовать reified с inline, что позволяет сохранить информацию о типе в рантайме. Альтернатива - передавать Class<T> как параметр. Для Android-контекста также часто используют KClass или проверку через when с приведением типов.
Подробное объяснение
В Kotlin, как и в Java, дженерики стираются на уровне JVM. Это значит, что внутри обычного обобщённого метода fun <T> check(value: T) компилятор не знает фактический тип T в рантайме. Поэтому конструкция value is T не скомпилируется - компилятор выдаст ошибку "cannot check for instance of erased type".
Решение - inline + reified. Ключевое слово reified позволяет использовать тип T как обычный класс внутри inline-функции. Компилятор подставляет фактический тип в место вызова, и проверка value is T становится возможной.
Важно понимать ограничения:
reifiedработает только сinline-функциями.- Нельзя использовать
reifiedв open-методах или методах, которые переопределяются. reifiedне работает с примитивами напрямую (но Kotlin автоматически оборачивает их в обёртки).- Проверка
isсreifiedработает корректно только для конкретных типов, не для generic-параметров других функций.
Если inline нежелателен (например, из-за размера кода), передают Class<T> или KClass<T> как параметр и используют isInstance или isAssignableFrom.
На практике
В Android-разработке reified часто используют для упрощения работы с Gson, Moshi, Retrofit, ViewModel и SharedPreferences. Например, типичная функция для чтения из SharedPreferences с приведением типа. Также reified удобен для создания экземпляров через рефлексию, например, для ViewModelProvider.
На собеседовании важно показать понимание trade-off: inline увеличивает размер байткода, но даёт возможность работать с типом в рантайме. Также стоит упомянуть, что reified - это compile-time подстановка, а не магия в рантайме.
Пример кода
// Проверка типа с reified inline fun <reified T> checkType(value: Any): Boolean { return value is T } // Использование val result = checkType<String>("hello") // true val result2 = checkType<Int>("hello") // false // Альтернатива без reified fun <T> checkTypeWithClass(value: Any, clazz: Class<T>): Boolean { return clazz.isInstance(value) } // Пример для Android: чтение из SharedPreferences inline fun <reified T> SharedPreferences.getPref(key: String, default: T): T { val value = when (T::class) { String::class -> getString(key, default as String) Int::class -> getInt(key, default as Int) Boolean::class -> getBoolean(key, default as Boolean) else -> throw IllegalArgumentException("Unsupported type") } return value as T }
Как отвечать на собеседовании
Начни с проблемы: type erasure в JVM. Затем объясни два подхода: reified с inline и передача Class. Подчеркни, что reified - это синтаксический сахар, который подставляет тип на этапе компиляции. Приведи пример из Android-практики, например, работу с SharedPreferences или Gson. Упомяни ограничения: нельзя использовать в open-функциях, увеличивается размер кода. Если спросят про производительность - скажи, что inline может даже улучшить её за счёт устранения вызова функции.
Что проверяет интервьюер
Интервьюер проверяет:
- понимание дженериков и type erasure;
- знание ключевого слова
reifiedи его ограничений; - умение применять это в реальных Android-сценариях;
- осознание trade-off между
inlineи передачейClass; - способность объяснить разницу между compile-time и runtime.
Типичные ошибки
- Попытка использовать
is Tбезreified- ошибка компиляции. - Забывают, что
reifiedтребуетinline. - Используют
reifiedв open-методах или интерфейсах - не скомпилируется. - Путают
isсas-asне проверяет тип, а приводит, может бросить исключение. - Не учитывают, что
reifiedработает только с конкретными типами, не с generic-параметрами других функций. - В Android-контексте забывают про стирание типов в
Gson-TypeTokenнужен именно из-за этого.
> Похожие задачи по mobile
Можно ли изменить значение val в дата классе через рефлексию
Что такое contracts в Kotlin и когда их используют?
Что такое Coroutine Builders в Kotlin
Что делают функции all и any в Kotlin и как их использовать для проверки условий
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью