---
title: "Inline em Kotlin: O que É e Como Funciona | Kotlin Brasil"
url: "https://kotlin.dev.br/glossario/inline/"
markdown_url: "https://kotlin.dev.br/glossario/inline.MD"
description: "Saiba o que é inline em Kotlin, como funciona a otimização de funções com lambdas e quando usar no seu código."
date: "2026-02-11"
author: "Karina Melo"
---

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

Saiba o que é inline em Kotlin, como funciona a otimização de funções com lambdas e quando usar no seu código.


## O que é `inline` em Kotlin?

O modificador `inline` em Kotlin instrui o compilador a **copiar o corpo da função diretamente no local da chamada**, em vez de criar uma chamada de função normal. Isso elimina o overhead de criação de objetos para lambdas, melhorando a performance.

Toda vez que você passa uma lambda como argumento, o Kotlin normalmente cria um objeto anônimo. Com `inline`, esse objeto não é criado — o código da lambda é copiado diretamente.

### Sem inline vs com inline

```kotlin
// Sem inline: cria um objeto Function para cada chamada
fun semInline(bloco: () -> Unit) {
    bloco()
}

// Com inline: codigo é copiado no local da chamada
inline fun comInline(bloco: () -> Unit) {
    bloco()
}
```

Na prática, o resultado é o mesmo. A diferença é por baixo dos panos: a versão `inline` não aloca um objeto `Function`.

### Exemplo prático: medindo tempo

```kotlin
inline fun medirTempo(bloco: () -> Unit) {
    val inicio = System.currentTimeMillis()
    bloco()
    val fim = System.currentTimeMillis()
    println("Tempo: ${fim - inicio}ms")
}

fun main() {
    medirTempo {
        val soma = (1..1_000_000).sum()
        println("Soma: $soma")
    }
}
```

### Non-local return

Uma vantagem do `inline` é permitir **non-local return** — retornar da função que chamou, não só da lambda:

```kotlin
inline fun buscarPrimeiro(lista: List<Int>, condicao: (Int) -> Boolean): Int? {
    for (item in lista) {
        if (condicao(item)) return item
    }
    return null
}

fun main() {
    val resultado = buscarPrimeiro(listOf(1, 3, 5, 8, 10)) { it % 2 == 0 }
    println(resultado) // 8
}
```

### `noinline` e `crossinline`

Se a função tem vários parâmetros lambda e você não quer inlinear todos:

```kotlin
inline fun exemplo(
    inlineada: () -> Unit,
    noinline naoInlineada: () -> Unit
) {
    inlineada()
    naoInlineada()
}
```

E `crossinline` impede non-local return em lambdas que serão executadas em outro contexto:

```kotlin
inline fun executarEmThread(crossinline bloco: () -> Unit) {
    Thread {
        bloco() // crossinline impede "return" aqui
    }.start()
}
```

O `crossinline` é necessário quando a lambda será executada em um contexto diferente (como outra thread ou callback), onde um non-local return não faz sentido e causaria comportamento indefinido.

### Quando usar?

Use `inline` em funções que recebem lambdas como parâmetro e são chamadas com frequência. A biblioteca padrão do Kotlin usa `inline` em `let`, `apply`, `map`, `filter` e praticamente todas as scope functions.

### Reified type parameters

O `inline` desbloqueia uma funcionalidade exclusiva: os **reified type parameters**. Normalmente, tipos genéricos são apagados em runtime (type erasure), mas com `inline` e `reified` você pode acessá-los:

```kotlin
inline fun <reified T> converterPara(json: String): T {
    println("Convertendo para ${T::class.simpleName}")
    // Em um caso real, usaria uma biblioteca como Gson ou kotlinx.serialization
    throw NotImplementedError("Exemplo ilustrativo")
}

inline fun <reified T> List<*>.filtrarPorTipo(): List<T> {
    return this.filterIsInstance<T>()
}

fun main() {
    val misturado: List<Any> = listOf(1, "texto", 2.5, "outro", 3)
    val strings = misturado.filtrarPorTipo<String>()
    println(strings) // [texto, outro]

    val inteiros = misturado.filtrarPorTipo<Int>()
    println(inteiros) // [1, 3]
}
```

Sem `inline`, seria necessário passar a classe como parâmetro: `fun <T> converter(json: String, tipo: Class<T>)`. Com `reified`, a API fica muito mais limpa.

### Inline properties

Além de funções, Kotlin permite marcar getters e setters de propriedades como `inline`:

```kotlin
class Configuracao(private val mapa: Map<String, String>) {
    inline val versao: String
        get() = mapa["versao"] ?: "1.0.0"

    inline val ambiente: String
        get() = mapa["ambiente"] ?: "desenvolvimento"
}
```

Isso é útil quando a propriedade não tem backing field e o getter é simples o suficiente para ser copiado no local de uso.

### Casos de Uso no Mundo Real

- **Scope functions da biblioteca padrão**: `let`, `run`, `with`, `apply` e `also` são todas `inline`, o que significa que usá-las não tem custo de performance em relação a escrever o código diretamente.
- **DSLs type-safe**: frameworks como Jetpack Compose e Ktor usam funções `inline` para criar DSLs onde o código do usuário é inlineado, mantendo a performance e permitindo non-local returns.
- **Serialização e deserialização**: bibliotecas usam `inline` com `reified` para inferir o tipo de destino automaticamente, como `json.decodeFromString<MeuObjeto>(texto)` em kotlinx.serialization.
- **Logging condicional**: funções inline de log como `logger.debug { "mensagem cara: ${calcular()}" }` evitam a construção da string quando o nível de log está desabilitado, já que o lambda só é avaliado se necessário.

### Boas Práticas

- Use `inline` apenas em funções que recebem lambdas. Marcar funções sem parâmetros de função como `inline` traz pouco benefício e pode aumentar o tamanho do bytecode.
- Marque com `noinline` parâmetros lambda que precisam ser armazenados em variáveis, passados para outras funções não-inline ou usados como objetos.
- Prefira `crossinline` quando a lambda será executada em outro contexto (threads, callbacks) para evitar bugs sutis com non-local returns.
- Combine `inline` com `reified` para criar APIs mais limpas que não exigem passagem explícita de `Class<T>` ou `KClass<T>`.
- Monitore o tamanho do bytecode gerado. Funções inline muito grandes chamadas em muitos lugares podem aumentar significativamente o tamanho do APK ou JAR.

### Erros Comuns

- **Tornar todas as funções inline indiscriminadamente**: o `inline` copia o corpo da função em cada local de chamada. Funções grandes inlineadas em muitos lugares inflam o bytecode sem ganho real de performance.
- **Esquecer de marcar parâmetros como `noinline` quando necessário**: se você tenta armazenar uma lambda inline em uma variável ou passá-la para outra função, o compilador gera um erro. A solução é marcar esse parâmetro como `noinline`.
- **Non-local return inesperado**: em funções `inline`, um `return` dentro da lambda retorna da função que chamou, não apenas da lambda. Isso pode causar comportamento inesperado se você esperava apenas sair do bloco.
- **Usar `inline` em funções de interface ou virtuais**: funções `inline` não podem ser `open`, `override` ou abstratas, pois o compilador precisa do corpo da função em tempo de compilação para copiar.
- **Confundir `reified` com reflexão**: `reified` funciona apenas em tempo de compilação dentro de funções `inline`. Você não pode usar `reified` em funções não-inline ou armazenar o tipo em uma variável para uso posterior.

### Perguntas Frequentes

**O `inline` melhora a performance de toda função?** Não. O benefício principal é evitar a alocação de objetos `Function` para lambdas. Em funções que não recebem lambdas, o ganho é mínimo e o custo de aumento do bytecode pode não valer a pena.

**Qual a diferença entre `noinline` e `crossinline`?** `noinline` impede completamente o inlining da lambda, permitindo que ela seja tratada como objeto. `crossinline` mantém o inlining mas proíbe non-local returns, necessário quando a lambda é executada em outro contexto como uma thread.

**Por que as scope functions do Kotlin são inline?** Para que o uso de `let`, `apply`, `run` e similares tenha zero overhead. Sem `inline`, cada chamada criaria um objeto `Function`, o que seria inaceitável para funções tão frequentemente utilizadas.

**Posso usar `reified` sem `inline`?** Não. O modificador `reified` só funciona em funções `inline` porque depende do compilador substituir o tipo genérico pelo tipo concreto no local de chamada. Sem inlining, o tipo seria apagado por type erasure.

### Termos Relacionados

- [Higher-Order Function](/glossario/higher-order-function) — funções que recebem lambdas e são as principais candidatas para `inline`
- [Lambda](/glossario/lambda) — funções anônimas cujo overhead de alocação é eliminado por `inline`
- [Generics](/glossario/generics) — tipos genéricos que podem ser preservados em runtime com `reified` e `inline`
- [Fun](/glossario/fun) — palavra-chave usada para declarar funções que podem receber o modificador `inline`
