companion object — mekanismen i Kotlin som ersätter nyckelordet static från Java för att deklarera statiska medlemmar i en klass. Kotlin har ingen inbyggd static — istället används en object-deklaration med modifieraren companion inuti klassen. Enligt JetBrains, 2025 gör companion object det möjligt att anropa metoder och egenskaper via klassnamnet, vilket gör dem till en fullständig motsvarighet till statiska medlemmar i Java-ekosystemet.
Huvudpunkter
companion object — är en speciell typ av object declaration i Kotlin som markeras med nyckelordet companion. Den gör det möjligt att deklarera medlemmar som tillhör klassen, inte dess instanser — det vill säga statiska medlemmar i Java-terminologi. Till skillnad från Java där static är en modifierare för enskilda fält och metoder, grupperas i Kotlin statiska medlemmar inom ett enda följeobjekt.
Varje klass i Kotlin kan innehålla exakt ett companion object. Medlemmarna i detta objekt är tillgängliga via klassnamnet utan att skapa en instans: MyClass.method(). Samtidigt, ur bytekodsperspektiv, kompileras companion object till en separat inre klass och dess metoder blir statiska metoder i den yttre klassen när annoteringen @JvmStatic används.
Enligt Google I/O 2024 har companion object blivit det huvudsakliga mönstret för fabriksmetoder, konstanter och hjälpfunktioner i moderna Android-applikationer i Kotlin. Utvecklare väljer det framför hjälpklasser med paketfunktioner, eftersom companion object behåller den logiska kopplingen till ägarklassen.
Använd companion object för att gruppera statisk kontext — konstanter, fabriker, hjälpmetoder som logiskt hör till klassen men inte kräver någon instans.
Grundläggande syntax för companion object är enkel: nyckelordet companion placeras före object-deklarationen inuti klassen. Om inget namn anges får objektet namnet Companion, som man kan referera till explicit eller implicit.
class User {
companion object {
const val TABLE_NAME = "users"
fun create(name: String): User {
return User(name)
}
}
val name: String
constructor(name: String) { this.name = name }
}
// Åtkomst via klassnamn
val table = User.TABLE_NAME
val user = User.create("Alice")
I exemplet ovan är TABLE_NAME och create() tillgängliga via User.TABLE_NAME och User.create(). Observera modifieraren const för primitiva konstanter — den garanterar att värdet bäddas in vid kompilering, analogt med Java static final för primitiver och String.
Om companion object inte har något namn kan man komma åt det via det automatiska namnet Companion: User.Companion.TABLE_NAME. I praktiken behövs detta sällan, men det är användbart vid anrop från Java-kod eller vid användning av reflektion.
// Båda anropen är likvärdiga
User.create("Bob")
User.Companion.create("Bob")
// Hämta referens till companion object
val companion: User.Companion = User
Ett companion object kan ha ett namn, vilket förbättrar kodens läsbarhet och gör det möjligt att referera till det med ett begripligt namn. Factory — det vanligaste namnet för ett companion object som används som fabrik.
class HttpResponse {
companion object Factory {
fun ok(body: String): HttpResponse = HttpResponse(200, body)
fun notFound(): HttpResponse = HttpResponse(404, "Not Found")
fun serverError(): HttpResponse = HttpResponse(500, "Internal Error")
}
}
// Åtkomst via Factory-namn
val response = HttpResponse.Factory.ok("data")
Ett namngivet companion object hjälper till att dokumentera syftet med statiska medlemmar. Vid omfaktorisering gör namnet koden självdokumenterande — utvecklaren ser direkt att Factory skapar instanser av HttpResponse.
En klass kan bara innehålla ett companion object. Detta är en grundläggande skillnad från Java, där man kan deklarera hur många statiska fält och metoder som helst utan gruppering. Om flera logiska grupper av statiska medlemmar behövs, använd nästlade object-deklarationer utan companion.
Enligt den officiella Kotlin-dokumentationen (Kotlin Docs, 2025) motiveras begränsningen till ett companion object av språkets design: statiska medlemmar bör vara nära kopplade till klassen, och ett enda följeobjekt ger en tydlig gräns för denna koppling. Om det finns för många statiska medlemmar — är det en signal för omfaktorisering av klassen.
I Kotlin kan även gränssnitt innehålla ett companion object. Detta gör det möjligt att definiera statiska metoder och konstanter direkt inuti gränssnittet, vilket inte är möjligt i Java. Denna metod används ofta för att deklarera konstanter som är kopplade till gränssnittet eller fabriksmetoder.
interface ApiService {
companion object {
const val BASE_URL = "https://api.example.com"
const val TIMEOUT_MS = 5000
fun create(client: OkHttpClient): ApiService =
Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.build()
.create(ApiService::class.java)
}
}
I detta exempel tillhör BASE_URL, TIMEOUT_MS och create() gränssnittet ApiService, inte dess implementationer. Detta är bekvämt: alla konstanter och fabrikslogik för att skapa en instans av API-tjänsten finns på ett ställe — inuti själva gränssnittet.
Implementationer av gränssnittet ärver inte medlemmarna i companion object — de anropas endast via gränssnittets namn: ApiService.BASE_URL.
När man anropar metoder från companion object i Java-kod är de som standard tillgängliga som metoder i den nästlade klassen Companion, inte som statiska metoder i den yttre klassen. För att exportera dem som riktiga static-metoder och -fält för Java, använd annoteringen @JvmStatic för metoder och @JvmField för fält.
| Annotering | Användning | Resultat i Java |
|---|---|---|
| @JvmStatic | Metoder i companion object | Statisk metod: ClassName.method() |
| @JvmField | Fält i companion object | Statiskt fält: ClassName.field |
| const | Primitiver och String | Inline-konstant: kompilatorn ersätter värdet |
| utan annotering | Standardmetoder/fält | Companion.method() / Companion.field |
class MathUtils {
companion object {
const val PI = 3.14159
@JvmStatic
fun square(x: Int): Int = x * x
@JvmField
val TAG: String = "MathUtils"
}
}
// Anropas i Java som MathUtils.square(5), MathUtils.TAG
Användning av @JvmStatic rekommenderas för alla publika metoder i companion object som ska vara tillgängliga från Java-kod. const tillämpas endast på primitiva typer och String — för andra typer använd @JvmField.
I verkliga projekt används companion object för flera standardsituationer. Fabriksmetoder — det vanligaste mönstret: istället för flera konstruktorer med olika signaturer används namngivna fabriksmetoder i companion object.
sealed class NetworkResult<out T> {
data class Success<out T>(val data: T) : NetworkResult<T>()
data class Error(val message: String) : NetworkResult<Nothing>()
companion object {
fun loading<T>(): NetworkResult<T> =
Loading()
}
}
private class Loading<T> : NetworkResult<T>()
Companion object i NetworkResult tillhandahåller fabriksmetoden loading() som skapar en Loading-instans med rätt generisk typ. Utan denna metod skulle man behöva skapa instansen direkt via Loading(), vilket avslöjar den interna implementationen.
Ofta används companion object för att lagra klasspecifika konstanter. Konstanter deklarerade med const val bäddas in vid kompilering, vilket ger noll overhead vid körning.
class UserRepository {
companion object {
private const val TAG = "UserRepository"
private const val CACHE_SIZE = 100
private const val DEFAULT_PAGE_SIZE = 20
}
}
Vanliga frågor
Ett ordinary object — är en fullvärdig singleton som existerar oberoende av klassen. companion object — är ett object inuti klassen vars medlemmar anropas via den yttre klassens namn. I bytekod blir companion object en statisk nästlad klass, medan ett vanligt object blir en autonom singleton-klass.
Nej, companion object ärvs inte av underklasser. Om klass B ärver klass A kommer B.method() inte att anropa en metod från klass A:s companion object — man måste gå via A.method(). Detta motsvarar beteendet hos statiska metoder i Java.
Som standard — via ClassName.Companion.method(). För att anropa som en statisk metod, lägg till @JvmStatic till metoden i companion object. För fält, använd @JvmField eller deklarera dem med const val för primitiver.
Kotlins utvecklare bestämde sig för att överge static till förmån för companion object för enhetlig hantering av objekt. Static i Java bryter mot OOP-principerna eftersom statiska metoder inte är bundna till en instans. Ett companion object — är ett förstklassigt objekt som kan skickas runt, utökas med tilläggsfunktioner och implementera gränssnitt.
Vid användning av const val för primitiver och String — noll overhead, värdet bäddas in i bytekoden. För metoder finns det ingen overhead om metoden inte är inline. I de flesta fall har companion object ingen mätbar påverkan på prestandan. Använd @JvmStatic endast för publikt API som anropas från Java.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också