Ответ
Companion object инициализируется при первом обращении к классу, в котором он объявлен, либо при первом обращении к самому companion object. Это происходит лениво (lazy initialization), аналогично статическим блокам в Java.
Пример:
class MyClass {
companion object {
init {
println("Companion initialized")
}
const val CONST_VALUE = 42
}
}
// Инициализация произойдет здесь:
val value = MyClass.CONST_VALUE
Важные особенности:
- Инициализируется только один раз (синглтон)
- Потокобезопасен (инициализация синхронизирована)
- Доступен без создания экземпляра класса
Ответ 18+ 🔞
А, ну это же про companion object в Kotlin! Давай разберём, как это работает, чтобы не было потом "ой, ёпта, а чё оно не так".
Представь себе класс — это как твоя квартира. Внутри неё живут обычные свойства и методы — это как ты сам, ходишь, чай пьёшь. А companion object — это типа встроенная кладовка в прихожей. Она принадлежит квартире, но чтобы в неё залезть, не надо каждый раз открывать дверь в гостиную и проходить через весь дом. Подошёл к двери квартиры, открыл дварцу в стеночке — и всё, ты в ней.
И главное — эта кладовка создаётся лениво. То есть её не строят, пока ты в неё первый раз не полезешь. Пока ты не сказал MyClass.CONST_VALUE, там пусто и тихо. Как только полез — ёперный театр! — раз! и кладовка построилась, загрузилась и выдала тебе твой CONST_VALUE.
Вот смотри на код, тут всё понятно:
class MyClass {
companion object {
init {
println("Companion initialized")
}
const val CONST_VALUE = 42
}
}
// Инициализация произойдет здесь:
val value = MyClass.CONST_VALUE
До этой строчки val value = MyClass.CONST_VALUE твой companion object — это просто идея, чертёж. Он нихуя не делает. Но как только ты к нему обратился — вжух! — выполняется блок init, создаётся объект-компаньон (один на весь класс, синглтон, блять) и тебе отдаётся константа.
И три главных фишки, которые надо запомнить, а то будешь потом бздеть, что что-то не работает:
- Создаётся один раз и навсегда. Это синглтон. Не будет такого, что для каждого экземпляра
MyClassсвоя кладовка. Нет, она одна на всех. Доверия ебать ноль к тому, кто говорит обратное. - Потокобезопасен. Это значит, если два потока одновременно рванутся к
CONST_VALUEв первый раз, они не создадут две кладовки. Один поток её построит, другой подождёт. Всё чинно, благородно, без гомосеков, налетевших на общий ресурс. - Доступен без создания экземпляра класса. Это же и есть вся соль! Чтобы взять что-то из кладовки, тебе не надо заселяться в квартиру (создавать объект
MyClass()). Подошёл к фасаду здания (к имени класса) — и всё, пользуйся. Удобно, хитрая жопа эти kotlin'овцы придумали.
Короче, если нужно место для констант, фабричных методов или какой-нибудь общей хуйни, которая логически привязана к классу, но не требует его инстанса — твоё место в companion object. Просто помни, что он ленивый, и инициализируется только когда его впервые потревожат.