Что такое стирание типов

Ответ

Стирание типов (type erasure) — это процесс, при котором информация о generic-типах удаляется во время компиляции. В runtime JVM видит только сырые типы (raw types), что может привести к ограничениям.

Пример:

val list1: List<String> = listOf("a", "b")
val list2: List<Int> = listOf(1, 2)
// В runtime оба списка будут просто List без информации о типах

Последствия:

  • Невозможно проверить generic-тип в runtime (if (list is List<String>) — ошибка)
  • Приводит к unchecked cast warnings
  • Для обхода используют reified-параметры в inline-функциях

Решение для проверки типов:

inline fun <reified T> checkType(item: Any) = item is T

Ответ 18+ 🔞

А, ну вот, опять про эти ваши дженерики. Слушай, история смешная, но сначала объясню, как есть. Есть у нас в Котлине такая штука — стирание типов. По-русски: компилятор, когда видит List<String> и List<Int>, он их нахуй стирает. В смысле, не сам список, а информацию, что внутри. В рантайме JVM смотрит на оба этих списка и видит просто голый, ебаный List, без всяких там <String>.

Представь себе: ты пришёл в магазин, купил пакет. На пакете написано «Сахар». Ты пришёл домой, а там вместо сахара — соль. Потому что на этапе упаковки кто-то хуйни накосячил и стёр надпись. Вот примерно так и тут. Компилятор — тот самый работяга, который затирает надписи на пакетах, чтобы JVM не парилась.

Вот, смотри, пример простой:

val list1: List<String> = listOf("a", "b")
val list2: List<Int> = listOf(1, 2)
// В рантайме оба списка будут просто List, без понятия, что внутри строка или циферка.

И вот из-за этого вылезают, блядь, последствия, которые мозг выносят:

  1. Проверить тип нахуй нельзя. Хочешь сделать if (list is List<String>) — получишь ошибку сразу, на этапе компиляции. Компилятор тебе скажет: «Чувак, ты чего? Я же только что стёр, какой там String. Откуда я знаю в рантайме, что там было?» И будет прав, сука.
  2. Предупреждения про unchecked cast. Это когда ты кастуешь что-то наугад, и компилятор тебе тихонько так говорит: «Слушай, я не уверен, что это безопасно, но если ты настоящий дебил — делай». Выглядит как (list as List<String>). Рисковано, ёпта.
  3. Для обхода этой хуйни придумали reified-параметры в inline-функциях. Это такая магия, которая говорит компилятору: «Не стирай, блядь, этот тип, мне он ещё нужен будет в рантайме».

Вот решение, как тип проверить:

inline fun <reified T> checkType(item: Any) = item is T

Короче, reified — это как волшебный пинок под жопу системе типов. Он позволяет сохранить информацию о типе T и использовать её в рантайме, потому что inline-функция по сути встраивает свой код на место вызова, и компилятор уже точно знает, с каким конкретным типом он имеет дело. Без этого — нихуя не выйдет, только сырые типы и предупреждения.