TGViewer
Kotlin Kotlin @kotlin_lib · 2.05K subscribers
Post #670 888
🩸 Value Classes: Когда «оптимизация» убивает перформанс

Мы привыкли думать, что value class - это серебряная пуля для Type Safety без оверхеда. Обернули Int в UserId, и в рантайме это просто int, верно?

Не всегда. Есть сценарии, где value class начинает вести себя хуже, чем обычный data class, порождая скрытый боксинг на ровном месте.

Рассмотрим классический кейс: попытка написать обобщенный обработчик.


@JvmInline
value class UserId(val id: Int)

fun <T> handle(item: T) {
// Какая-то логика
println(item)
}

fun main() {
val uid = UserId(42)
handle(uid) // <--- Здесь происходит магия (плохая)
}



Что происходит под капотом?

В момент вызова handle(uid) компилятор сталкивается с проблемой. Функция handle ожидает T (который в JVM стирается до Object), а UserId в скомпилированном виде - это примитив int.

Чтобы передать int туда, где ожидается Object, JVM обязана его упаковать.

1. Создается экземпляр-обертка UserId в куче (heap allocation).
2. Этот объект передается в функцию.
3. Если внутри функции мы снова кастуем его к конкретному типу, происходит анбоксинг.

Еще хуже: Интерфейсы

Если ваш value class реализует интерфейс, и вы работаете с ним через ссылку на этот интерфейс - вы гарантированно получаете боксинг.


interface Identity {
fun raw(): Int
}

@JvmInline
value class GroupId(val id: Int) : Identity {
override fun raw() = id
}

fun process(id: Identity) { ... } // 100% боксинг при вызове



Почему это важно?

Если вы используете value classes в горячих циклах (hot paths) или высоконагруженных стримах, думая, что экономите память, использование их в качестве дженериков или через интерфейсы приведет к обратному эффекту:

🖤GC Pressure: Вы создаете короткоживущие объекты-обертки тысячами.
🖤Снижение производительности: Аллокация + боксинг/анбоксинг стоят дороже, чем передача ссылки на обычный объект.

Как лечить?

1. Избегайте интерфейсов на value classes, если критична производительность.
2. Специализируйте функции. Вместо fun <T> handle(t: T) пишите перегрузки для конкретных value типов, если это возможно.
3. Ждите Project Valhalla. Настоящие примитивные классы в JVM решат эту проблему фундаментально, но пока мы живем с ограничениями Type Erasure.

Итог: value class идеален для доменной модели и сигнатур функций, но будьте предельно осторожны, как только они попадают в полиморфный контекст.

#kotlin #performance #jvm #senior

✍️ @kotlin_lib
  • 👍 4
  • ❤ 2
More from @kotlin_lib
  1. Aug 26, 2026🚧 Ваш Mutex тормозит корутины. Как перестать лочить и начать жить Вы пишете многопоточный…
  2. Jul 25, 2026🚀 Подборка полезных IT каналов в Max Системное администрирование, DevOps 📌 https://max.r…
  3. Jul 1, 2026🌪 Ваша дата в опасности: flatMapConcat vs Merge vs Latest Вам нужно взять поток ID-шников…
  4. Jun 24, 2026🤖 Android-приложение — это не только красивый экран. За ним стоят работа с внешним API, з…
  5. Jun 23, 2026🔮 Убийца бойлерплейта: Встречайте Context Parameters (Kotlin 2.x) Мы так привыкли к Depen…
  6. Jun 3, 2026Яндекс обновил Yandex Mobile Ads SDK для монетизации мобильных приложений — и это интересн…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →