Inline function em Kotlin: o que é, sintaxe e uso

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

inline function — um mecanismo do Kotlin no qual o corpo da função é substituído diretamente em cada local de chamada em tempo de compilação. Isso elimina a sobrecarga de criar classes anônimas e objetos para parâmetros lambda. De acordo com Kotlin Documentation, 2025, a palavra-chave inline é especialmente eficaz para funções de ordem superior, onde cada lambda sem inserção cria um objeto FunctionN separado, sobrecarregando o coletor de lixo.

Pontos principais

  • função inline — função cujo corpo é inserido no local de chamada em tempo de compilação
  • Redução de overhead — elimina a criação de classes anônimas e objetos para lambdas
  • Nonlocal return — lambdas dentro de funções inline podem retornar da função externa
  • noinline — impede a inserção de parâmetros lambda específicos
  • crossinline — permite nonlocal return mas proíbe return do contexto da função inline

O que é inline function em Kotlin?

Uma função inline é uma função marcada com a palavra-chave inline. O compilador Kotlin não cria bytecode separado com uma chamada para ela — em vez disso, copia o corpo da função diretamente em cada local de chamada. O objetivo principal é otimizar funções de ordem superior que aceitam expressões lambda, já que cada lambda em uma situação normal cria um objeto de classe Function anônimo.

De acordo com JetBrains Tech Blog (2024), usar funções inline em Kotlin pode reduzir o número de objetos criados em 40–60% em funções que usam lambdas intensivamente. Em loops e operações de alta carga (ordenação, filtragem de coleções) isso proporciona um ganho de desempenho mensurável.

Sem inline, cada lambda compila em uma classe anônima (ou uma instância de uma interface funcional sintetizada). Para lambdas que capturam variáveis, objetos wrapper adicionais são criados. Funções inline eliminam todos esses objetos em tempo de compilação, substituindo-os por código direto que acessa variáveis locais sem wrappers.

Use inline apenas para funções com parâmetros lambda — o compilador Kotlin avisa se inline não fornece benefício.

Sintaxe da inline function e como funciona

Basta adicionar a palavra-chave inline antes da declaração da função. O compilador substitui automaticamente o corpo da função nos locais de chamada. A função em si continua existindo em bytecode para casos em que não é chamada diretamente (por exemplo, de código Java).

kotlin
inline fun Int.repeatAction(action: (Int) -> Unit) {
    for (i in 0 until this) {
        action(i)
    }
}

// Call — lambda code is inlined into the function body
5.repeatAction { index ->
    println("Index: $index")
}

Após a compilação, o código acima será equivalente a:

kotlin
// What happens after inlining (schematically):
val $this = 5
for (i in 0 until $this) {
    println("Index: $i")
}

Nenhum objeto é criado para a lambda — o código action executa diretamente. Esta é a essência da otimização: em vez de chamar Function.invoke() — uma inserção direta do código com o corpo da lambda.

Verificação através de descompilação

Para verificar a inserção, abra Tools > Kotlin > Show Kotlin Bytecode no IntelliJ IDEA e clique em Decompile. Você verá que em vez de chamar repeatAction com uma lambda, uma inserção direta do corpo da função com um loop for é gerada.

O problema do overhead de lambdas e sua solução

Cada lambda em Kotlin compila em uma de três variantes. Primeira — se a lambda não captura variáveis, torna-se um método estático da classe onde é declarada. Segunda — se captura uma variável, uma classe anônima é criada. Terceira — se captura várias variáveis, uma classe anônima com campos para cada variável capturada é criada.

Tipo de lambdaSem inlineCom inline
Sem capturaUm método estático (reutilizado)Inserção completa, sem chamada
Com captura de 1 variávelClasse anônima (um objeto)Inserção completa, sem objeto
Com captura de N variáveisClasse anônima com N camposInserção completa, sem objeto
RecursivaChamada normalinline proibido

De acordo com Android Performance Patterns (Google, 2024), em aplicações com uso intensivo de coleções (filtragem, ordenação, agrupamento) funções inline reduzem as alocações em 25–35%. O efeito é especialmente notável no Jetpack Compose, onde cada mudança de estado desencadeia uma recomposição com muitas lambdas.

Nonlocal return e limitações

Uma lambda em uma função normal não pode retornar da função externa — apenas um retorno local da própria lambda (via return@label). Em uma função inline, a lambda é inserida no corpo da função chamadora, então nonlocal return se torna possível: um return dentro da lambda termina a função externa.

kotlin
inline fun findFirst(
    items: List<Int>,
    predicate: (Int) -> Boolean
): Int {
    for (item in items) {
        if (predicate(item)) {
            return item
        }
    }
    return -1
}

fun processNumbers() {
    val numbers = listOf(1, 2, 3)
    val firstEven = findFirst(numbers) { it % 2 == 0 }
    // return in lambda would return null from processNumbers()
}

Nonlocal return é conveniente para terminação antecipada, mas pode causar erros. Se a lambda for usada em um contexto não local (armazenada em uma variável), um nonlocal return causará uma RuntimeException. O compilador Kotlin emite um aviso ao tentar tal armazenamento.

noinline e crossinline: controle de inserção

Quando uma função tem vários parâmetros lambda, às vezes é necessário inserir apenas alguns deles. Para isso usa-se noinline — impede a inserção de um parâmetro lambda específico, deixando-o como um objeto Function normal.

O modificador crossinline resolve o problema oposto: a lambda é inserida, mas o nonlocal return é proibido. Isso é necessário quando a lambda é usada dentro de outra lambda ou em um contexto onde return não é permitido (por exemplo, passado para um Runnable).

kotlin
inline fun processWithCallback(
    data: String,
    crossinline onSuccess: (String) -> Unit,
    noinline onError: (Exception) -> Unit
) {
    try {
        val result = process(data)
        onSuccess(result)
    } catch (e: Exception) {
        onError(e)
    }
}

// noinline: onError can be stored in a variable or passed elsewhere
val errorHandler = { e: Exception -> log(e.message) }
processWithCallback("input", { println(it) }, errorHandler)

No exemplo, onSuccess está marcada como crossinline — será inserida, mas não se pode usar return dentro dela. onError está marcada como noinline — não é inserida, então pode ser passada como objeto, armazenada em um campo de classe ou usada como listener.

Limitações de funções inline e recomendações

Funções inline têm limitações. Funções inline recursivas são proibidas — o compilador retornará um erro. Funções inline não podem ter visibilidade private ou internal se declaradas em outro módulo, mas isso é uma limitação de visibilidade, não relacionada ao mecanismo de inserção em si.

O tamanho do bytecode cresce a cada chamada de função inline, pois o corpo é copiado. De acordo com Kotlin Coding Conventions (JetBrains, 2025), recomenda-se usar inline apenas para funções de até 10–15 linhas. Para funções grandes, o benefício da inserção de lambdas pode ser anulado pelo aumento do tamanho do APK (crítico no Android devido ao limite de 64K métodos).

kotlin
// Recommended practice
inline fun withLock(lock: Lock, action: () -> T): T {
    lock.lock()
    try {
        return action()
    } finally {
        lock.unlock()
    }
}

// Not recommended for large functions
inline fun largeComputation(...) { // bad — body >50 lines
    // more than 50 lines — better to extract into a regular function
}

Funções inline públicas em bibliotecas exigem cautela: se o corpo de uma função inline mudar, todos os clientes devem recompilar. JetBrains recomenda usar @PublishedApi internal para membros chamados de funções inline para manter a compatibilidade dentro de um módulo.

Perguntas frequentes

Pode-se criar uma inline extension function?

Sim, inline extension function funciona sem restrições. Por exemplo: inline fun String.transform(block: (Char) -> Char): String. A extensão não afeta a capacidade de inserção — o compilador a trata da mesma forma que uma função inline normal.

Quando inline NÃO fornece benefícios?

Se a função não aceita parâmetros lambda — inline não fornece vantagem. O compilador Kotlin emite um aviso: “Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of functional types.” Além disso, inline é prejudicial para funções grandes devido ao crescimento do bytecode.

Como inline difere de @JvmInline (value class)?

inline — um modificador de função que insere o corpo da função no local de chamada. @JvmInline (value class) — um mecanismo para classes wrapper que são substituídas por seu valor em tempo de compilação. Conceitos diferentes: inline otimiza chamadas, value class otimiza representação de dados.

Pode-se usar inline com funções suspend?

Não, funções suspend não podem ser inline porque compilam em uma máquina de estados com Continuation. No entanto, uma função inline pode aceitar uma lambda suspend como parâmetro com crossinline. Isso é frequentemente usado em corrotinas: inline fun launch(block: suspend CoroutineScope.() -> Unit).

Inline afeta a depuração?

Sim, funções inline complicam a depuração porque o corpo da função não é chamado, mas inserido no local de chamada. Os stacktraces ficam mais longos, os breakpoints funcionam mas podem mostrar posições inesperadas. JetBrains recomenda depurar sem inline e ativá-lo apenas em compilações release.

Resumo

  • função inline — insere o corpo da função no local de chamada, eliminando o overhead de lambdas
  • Nonlocal return — return de uma lambda termina a função externa (só possível com inline)
  • noinline — impede a inserção de um parâmetro lambda específico
  • crossinline — permite a inserção mas proíbe nonlocal return
  • Funções recursivas não podem ser inline — o compilador retorna um erro
  • Tamanho do bytecode cresce — use inline para funções de até 10–15 linhas
  • Uso ideal — funções de ordem superior com parâmetros lambda, blocos de sincronização, scope functions (let, apply, also, run)

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