---
title: "Companion Object em Kotlin: O que É e Como Funciona | Kotlin Brasil"
url: "https://kotlin.dev.br/glossario/companion-object/"
markdown_url: "https://kotlin.dev.br/glossario/companion-object.MD"
description: "Entenda o que é Companion Object em Kotlin, como funciona e como ele substitui membros estáticos do Java."
date: "2026-02-04"
author: "Karina Melo"
---

# Companion Object em Kotlin: O que É e Como Funciona | Kotlin Brasil

Entenda o que é Companion Object em Kotlin, como funciona e como ele substitui membros estáticos do Java.


## O que é Companion Object em Kotlin?

O `companion object` é um objeto especial declarado **dentro de uma classe** que funciona como o equivalente aos membros estáticos do Java. Com ele, você pode acessar propriedades e funções diretamente pelo nome da classe, sem precisar criar uma instância.

Kotlin não tem a palavra-chave `static`. Em vez disso, usa companion objects -- uma abordagem mais flexível e orientada a objetos.

Pense no companion object como a "recepção" de um prédio comercial. Você não precisa entrar em nenhuma sala específica (instância) para obter informações gerais -- basta perguntar na recepção. Da mesma forma, o companion object guarda informações e funcionalidades que pertencem à classe como um todo, não a uma instância individual.

### Sintaxe básica

```kotlin
class Configuração {
    companion object {
        const val VERSAO = "2.1.0"
        val AMBIENTE = "producao"

        fun info(): String {
            return "Versão $VERSAO - Ambiente: $AMBIENTE"
        }
    }
}

fun main() {
    println(Configuração.VERSAO)    // 2.1.0
    println(Configuração.info())    // Versão 2.1.0 - Ambiente: producao
}
```

Repare que você acessa `versão` e `info()` direto pela classe, sem instanciar nada.

### Factory methods

Um dos usos mais comuns do companion object é para criar **factory methods** -- funções que constroem objetos de formas alternativas:

```kotlin
data class Usuario(val nome: String, val email: String) {
    companion object {
        fun criarAdmin(nome: String): Usuario {
            return Usuario(nome, "$nome@admin.com.br")
        }

        fun criarConvidado(): Usuario {
            return Usuario("Convidado", "convidado@temp.com.br")
        }
    }
}

fun main() {
    val admin = Usuario.criarAdmin("karina")
    val guest = Usuario.criarConvidado()

    println(admin)  // Usuario(nome=karina, email=karina@admin.com.br)
    println(guest)  // Usuario(nome=Convidado, email=convidado@temp.com.br)
}
```

### Companion object com nome e interface

O companion object pode ter um nome e até implementar interfaces:

```kotlin
interface Serializavel {
    fun fromJson(json: String): Any
}

class Produto(val nome: String) {
    companion object Fabrica : Serializavel {
        override fun fromJson(json: String): Produto {
            return Produto(json) // simplificado
        }
    }
}
```

### Quando usar?

Use companion object para constantes, factory methods, e qualquer funcionalidade que pertença à classe como um todo e não a uma instância específica. É o jeito Kotlin de lidar com o que seria `static` em Java.

### Companion object com extension functions

Você pode adicionar [extension functions](/glossario/extension-function/) ao companion object de uma classe, o que permite estender funcionalidades sem modificar o código original:

```kotlin
class Validador {
    companion object
}

fun Validador.Companion.cpf(valor: String): Boolean {
    return valor.replace("[^0-9]".toRegex(), "").length == 11
}

fun Validador.Companion.email(valor: String): Boolean {
    return valor.contains("@") && valor.contains(".")
}

fun main() {
    println(Validador.cpf("123.456.789-00")) // true
    println(Validador.email("teste@email.com")) // true
    println(Validador.email("invalido"))         // false
}
```

### Companion object como singleton de configuração

Um padrão muito utilizado é usar companion object para gerenciar configurações ou registros de uma classe:

```kotlin
class Logger private constructor(val nome: String) {
    companion object {
        private val instancias = mutableMapOf<String, Logger>()

        fun obter(nome: String): Logger {
            return instancias.getOrPut(nome) {
                println("Criando logger para: $nome")
                Logger(nome)
            }
        }
    }

    fun info(mensagem: String) {
        println("[$nome] INFO: $mensagem")
    }
}

fun main() {
    val logA = Logger.obter("App")
    val logB = Logger.obter("App")    // reutiliza a instância existente
    val logC = Logger.obter("Database")

    logA.info("Aplicação iniciada")
    logC.info("Conexão estabelecida")

    println(logA === logB) // true -- mesma instância
}
```

### Casos de Uso no Mundo Real

- **Constantes de configuração**: agrupar URLs de API, chaves de preferências, códigos de erro e outras constantes que pertencem ao contexto da classe.
- **Factory methods com válidação**: criar instâncias com regras de negócio, como `Usuario.fromCsv(linha)` ou `Pedido.criarRascunho()`.
- **Interoperabilidade com Java**: usar a anotação `@JvmStatic` em métodos do companion object para que o código Java possa chamar como métodos estáticos reais.
- **Serialização e desserialização**: implementar funções `fromJson()` e `fromMap()` no companion object para converter dados externos em objetos Kotlin.
- **Registros e caches**: manter um mapa de instâncias para evitar criação duplicada, como no padrão mostrado acima.

### Boas Práticas

- **Use `const val` para constantes primitivas**: dentro do companion object, declare constantes de tipos primitivos e String com `const val` para garantir que sejam inlined pelo compilador.
- **Não coloque lógica de negócio pesada** no companion object. Ele deve conter funcionalidades utilitárias relacionadas à classe, não regras complexas.
- **Dê um nome ao companion object** quando ele implementa uma [interface](/glossario/interface/) ou quando você quer deixar o propósito claro: `companion object Factory`.
- **Use `@JvmStatic`** em projetos mistos Kotlin/Java para facilitar a interoperabilidade.
- **Prefira [object](/glossario/object/) de nível superior** quando a funcionalidade não está diretamente ligada a uma classe específica.

### Erros Comuns

- **Confundir companion object com instância da classe**: o companion object é compartilhado entre todas as instâncias. Alterar uma propriedade `var` dentro dele afeta todas as partes do código que a acessam.
- **Usar companion object para estado mutável global**: isso cria acoplamento e dificulta testes. Se precisa de estado compartilhado, considere injeção de dependência.
- **Esquecer que cada classe só pode ter um companion object**: se você precisa de múltiplos agrupamentos, use [objects](/glossario/object/) regulares nomeados dentro da classe.
- **Não usar `const` em constantes String**: declarar `val` em vez de `const val` para strings constantes impede a otimização do compilador e gera um campo com getter desnecessário.

### Perguntas Frequentes

**Qual a diferença entre companion object e object declaration?**
O `companion object` vive dentro de uma classe e permite acessar seus membros pelo nome da classe (como `MinhaClasse.função()`). Um [object](/glossario/object/) declaration é um singleton independente, acessado pelo próprio nome.

**Posso ter mais de um companion object por classe?**
Não. Cada classe pode ter no máximo um companion object. Se precisar de mais agrupamentos, use `object` nomeados regulares dentro da classe.

**O companion object é inicializado quando?**
Ele é inicializado na primeira vez que a classe é referenciada, de forma similar ao carregamento de classes no Java. Isso segue o padrão de inicialização lazy.

**Como acessar o companion object de Kotlin a partir do Java?**
Use `MinhaClasse.Companion.método()`. Se quiser acessar como método estático, adicione `@JvmStatic` ao método dentro do companion object.
