Companion object em Kotlin: o que é, sintaxe e uso

Autor: IT Sectr Publicado: 2026-06-21 Tempo de leitura: 9 min

companion object é um mecanismo da linguagem Kotlin que substitui a palavra-chave static do Java para declarar membros estáticos de uma classe. Kotlin não possui static nativo — em vez disso, usa-se uma declaração object com o modificador companion dentro de uma classe. De acordo com JetBrains, 2025, companion object permite chamar métodos e propriedades através do nome da classe, tornando-os equivalentes completos aos membros estáticos no ecossistema Java.

Pontos Principais

  • companion object é uma declaração object dentro de uma classe com a palavra-chave companion, substituindo Java static
  • Membros estáticos acessíveis através do nome da classe sem criar uma instância: ClassName.method()
  • Companion object nomeado permite dar um nome ao objeto para um código mais legível
  • Interfaces em Kotlin também podem conter companion object com implementação de métodos
  • @JvmStatic — anotação para exportar métodos de companion object como métodos static reais em Java

O que é companion object em Kotlin?

companion object é um tipo especial de object declaration em Kotlin marcado com a palavra-chave companion. Ele permite declarar membros que pertencem à classe em vez de suas instâncias — ou seja, membros estáticos em termos Java. Diferente do Java, onde static é um modificador para campos e métodos individuais, em Kotlin os membros estáticos são agrupados dentro de um único objeto companheiro.

Qualquer classe em Kotlin pode conter exatamente um companion object. Os membros deste objeto são acessíveis através do nome da classe sem criar uma instância: MyClass.method(). Em termos de bytecode, um companion object é compilado como uma classe interna separada, e seus métodos tornam-se métodos estáticos da classe externa ao usar a anotação @JvmStatic.

De acordo com o Google I/O 2024, companion object tornou-se o padrão principal para métodos fábrica, constantes e funções auxiliares em aplicativos Android modernos escritos em Kotlin. Os desenvolvedores o escolhem em vez de classes utilitárias com funções de nível de pacote porque companion object mantém uma conexão lógica com a classe proprietária.

Use companion object para agrupar contexto estático — constantes, fábricas, métodos auxiliares que pertencem logicamente à classe mas não requerem uma instância.

Sintaxe do companion object: declaração e acesso

A sintaxe básica do companion object é simples: a palavra-chave companion é colocada antes da declaração object dentro da classe. Se nenhum nome for especificado, o objeto recebe o nome Companion, que pode ser acessado explícita ou implicitamente.

kotlin
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 }
}

// Access via class name
val table = User.TABLE_NAME
val user = User.create("Alice")

No exemplo acima, TABLE_NAME e create() são acessíveis via User.TABLE_NAME e User.create(). Observe o modificador const para constantes primitivas — ele garante a inserção do valor em tempo de compilação, similar ao Java static final para primitivos e String.

Acesso implícito e explícito via Companion

Se um companion object não tem nome, pode ser acessado através do nome automático Companion: User.Companion.TABLE_NAME. Na prática isso raramente é necessário, mas é útil ao chamar código Java ou ao usar reflexão.

kotlin
// Both calls are equivalent
User.create("Bob")
User.Companion.create("Bob")

// Getting reference to companion object
val companion: User.Companion = User

Companion object nomeado e características

Um companion object pode ter um nome, o que melhora a legibilidade do código e permite acessá-lo por um nome significativo. Factory é o nome mais comum para um companion object usado como fábrica.

kotlin
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")
    }
}

// Access via Factory name
val response = HttpResponse.Factory.ok("data")

Um companion object nomeado ajuda a documentar o propósito dos membros estáticos. Em refatoração, o nome torna o código autodocumentável — o desenvolvedor vê instantaneamente que Factory cria instâncias de HttpResponse.

Limitação: exatamente um companion object por classe

Uma classe pode conter apenas um companion object. Esta é uma diferença fundamental do Java, onde você pode declarar qualquer número de campos e métodos estáticos sem agrupamento. Se precisar de múltiplos grupos lógicos de membros estáticos, use declarações object aninhadas sem companion.

De acordo com a documentação oficial do Kotlin (Kotlin Docs, 2025), a limitação de um companion object é motivada pelo design da linguagem: membros estáticos devem estar fortemente acoplados à classe, e um objeto companheiro fornece um limite claro para essa conexão. Se houver muitos membros estáticos, é um sinal para refatorar a classe.

Companion object em interfaces

Em Kotlin, as interfaces também podem conter um companion object. Isso permite definir métodos estáticos e constantes diretamente dentro de uma interface, algo impossível em Java. Esta abordagem é frequentemente usada para declarar constantes relacionadas à interface ou métodos fábrica.

kotlin
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)
    }
}

Neste exemplo, BASE_URL, TIMEOUT_MS e create() pertencem à interface ApiService, não às suas implementações. Isso é conveniente: todas as constantes e a lógica de fábrica para criar uma instância do serviço API estão localizadas em um só lugar — dentro da própria interface.

As implementações da interface não herdam os membros do companion object — eles são chamados apenas através do nome da interface: ApiService.BASE_URL.

@JvmStatic e @JvmField: compatibilidade com Java

Ao chamar métodos de companion object do código Java, por padrão eles são acessíveis como métodos da classe interna Companion, não como métodos estáticos da classe externa. Para exportá-los como métodos e campos estáticos reais para Java, use a anotação @JvmStatic para métodos e @JvmField para campos.

AnotaçãoAplicaçãoResultado em Java
@JvmStaticMétodos de companion objectMétodo estático: ClassName.method()
@JvmFieldCampos de companion objectCampo estático: ClassName.field
constPrimitivos e StringConstante inline: o compilador substitui o valor
sem anotaçãoMétodos/campos por padrãoCompanion.method() / Companion.field
kotlin
class MathUtils {
    companion object {
        const val PI = 3.14159

        @JvmStatic
        fun square(x: Int): Int = x * x

        @JvmField
        val TAG: String = "MathUtils"
    }
}

// Called in Java as MathUtils.square(5), MathUtils.TAG

Recomenda-se usar @JvmStatic para todos os métodos públicos de companion object que devem ser acessíveis a partir de código Java. const aplica-se apenas a tipos primitivos e String — para outros tipos use @JvmField.

Exemplos práticos de uso do companion object

Em projetos reais, companion object é usado para vários cenários padrão. Métodos fábrica são o padrão mais comum: em vez de múltiplos construtores com assinaturas diferentes, usam-se métodos fábrica nomeados no companion object.

kotlin
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 em NetworkResult fornece um método fábrica loading() que cria uma instância Loading com o tipo genérico correto. Sem este método, você teria que criar uma instância diretamente via Loading(), o que expõe a implementação interna.

Constantes e tags de logging

companion object é frequentemente usado para armazenar constantes específicas da classe. Constantes declaradas com const val são inseridas em tempo de compilação, proporcionando zero overhead em tempo de execução.

kotlin
class UserRepository {
    companion object {
        private const val TAG = "UserRepository"
        private const val CACHE_SIZE = 100
        private const val DEFAULT_PAGE_SIZE = 20
    }
}

Perguntas Frequentes

Qual a diferença entre companion object e um object normal em Kotlin?

Um object normal é um singleton completo que existe independentemente da classe. companion object é um object dentro de uma classe cujos membros são chamados através do nome da classe externa. Em bytecode, um companion object torna-se uma classe aninhada estática, enquanto um object normal torna-se uma classe singleton autônoma.

Companion object pode ser herdado?

Não, companion object não é herdado por subclasses. Se a classe B estende a classe A, então B.method() não chamará o método do companion object da classe A — você precisa chamar A.method(). Isso corresponde ao comportamento dos métodos estáticos em Java.

Como chamar companion object a partir de código Java?

Por padrão — através de ClassName.Companion.method(). Para chamá-lo como método estático, adicione @JvmStatic ao método do companion object. Para campos, use @JvmField ou declare-os com const val para primitivos.

Por que não há palavra-chave static em Kotlin?

Os desenvolvedores do Kotlin decidiram abandonar static em favor do companion object para um trabalho uniforme com objetos. static em Java viola princípios de POO porque métodos estáticos não estão vinculados a uma instância. companion object é um objeto de primeira classe que pode ser passado, estendido com funções de extensão e implementar interfaces.

Companion object afeta o desempenho?

Ao usar const val para primitivos e String — zero overhead, o valor é inserido no bytecode. Para métodos, não há overhead a menos que o método seja inline. Na maioria dos casos, companion object não cria nenhum impacto mensurável no desempenho. Use @JvmStatic apenas para API pública chamada a partir de Java.

Resumo

  • companion object é um mecanismo Kotlin para declarar membros estáticos de classe, substituindo Java static
  • Um companion object por classe — agrupa todos os elementos estáticos em um único objeto companheiro
  • Acesso através do nome da classe: ClassName.method() ou ClassName.Companion.method()
  • @JvmStatic e @JvmField exportam membros como métodos e campos estáticos reais para Java
  • const val para primitivos e String — insere o valor em tempo de compilação com zero overhead
  • Interfaces também suportam companion object para constantes e métodos fábrica
  • Companion object nomeado melhora a legibilidade do código e autodocumenta o propósito dos membros estáticos

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também