Reified em Kotlin — o que é, sintaxe e uso

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

reified é uma palavra-chave em Kotlin que permite acessar o tipo do parâmetro genérico dentro de funções inline em tempo de execução. Em genéricos comuns, aplica-se type erasure — a informação do tipo é apagada em tempo de compilação, mas reified a preserva. De acordo com a Documentação Kotlin, 2025, reified só funciona dentro de funções inline porque o compilador substitui o tipo real no estágio de inline.

Pontos principais

  • reified — um modificador de parâmetro genérico que preserva informações do tipo em tempo de execução
  • Apenas inline — reified funciona exclusivamente dentro de funções inline
  • Type erasure — o mecanismo padrão Java/Kotlin que apaga tipos genéricos; reified o contorna
  • Verificações is — possíveis: if (value is T) em vez de if (value is String)
  • Criação de instâncias — T::class.java.newInstance() sem passar Class<T>

O que é reified em Kotlin?

reified é um modificador de um parâmetro genérico de uma função inline que torna o tipo real (reify — “tornar real”) em tempo de execução. Sem reified, o tipo T dentro de uma função genérica é inacessível — o compilador aplica type erasure, removendo todas as informações do tipo. reified obriga o compilador a substituir o tipo concreto no local da chamada, tornando-o acessível via T::class e o operador is.

De acordo com a Pesquisa Kotlin da Kodee (2024), os parâmetros de tipo reified estão entre as dez funcionalidades Kotlin mais demandadas — são usados por 52% dos desenvolvedores pesquisados, principalmente para escrever fábricas genéricas, contêineres DI e serializadores. reified é especialmente popular em combinação com Gson, Moshi e Kotlinx Serialization.

Tecnicamente, o mecanismo é simples: ao chamar uma função inline com um parâmetro reified, o compilador conhece o tipo de argumento concreto (Int, String, User) e o substitui por T. Em bytecode, o parâmetro reified se torna um Class<T> comum passado como argumento oculto.

Use reified para escrever funções genéricas onde o tipo é necessário em tempo de execução — criação de instâncias, verificações de tipo, obtenção de Class<T> para reflexão ou serialização.

O problema do type erasure em genéricos

Type erasure é um mecanismo em Java e Kotlin onde as informações dos parâmetros genéricos são apagadas durante a compilação. Em bytecode, List<String> e List<Int> se tornam apenas List. Isso foi feito para compatibilidade retroativa com Java 1.4, que não tinha genéricos, mas cria limitações ao trabalhar com tipos em tempo de execução.

kotlin
// ❌ Erro: Cannot check for instance of erased type
fun <T> checkType(value: Any) {
    if (value is T) { // type erasure — T is unknown
        println("Type matches")
    }
}

// ✅ Solution: pass Class as parameter
fun <T> checkTypeWithClass(
    value: Any,
    clazz: Class<T>
) {
    if (clazz.isInstance(value)) {
        println("Type matches")
    }
}

No exemplo, checkType não compila devido ao type erasure — o compilador não sabe qual tipo substituir por T. Em checkTypeWithClass, o problema é resolvido passando Class<T> explicitamente, mas isso requer boilerplate: cada chamada é acompanhada de .java ou ::class.java. reified elimina completamente esse boilerplate.

Sintaxe do reified e como funciona

O modificador reified é colocado antes do parâmetro genérico em uma função inline. A função deve ser inline — o compilador deve ser capaz de substituir o tipo concreto no estágio de inline.

kotlin
inline fun <reified T> isA(value: Any): Boolean {
    return value is T
}

fun main() {
    println(isA<String>("Hello")) // true
    println(isA<Int>("Hello"))  // false
}

Durante a compilação, a chamada isA<String>(“Hello”) é substituída pela verificação value is String. A chamada isA<Int>(“Hello”) se torna value is Int. O tipo é substituído literalmente, permitindo o uso de is, as, ::class e outras operações indisponíveis com type erasure.

Decompilação de uma função reified

Se vocé descompilar o bytecode de isA<String>(“Hello”), o IntelliJ IDEA mostrará aproximadamente este resultado em Java: String.class.isInstance(value). Em vez de um parâmetro genérico, o compilador substituiu o java.lang.String.class concreto — sem reflexão com busca de tipo por nome, apenas uma referência direta à classe.

Verificações de tipo com reified: is e as

O uso mais comum do reified é a verificação de tipos através do operador is. Em uma função genérica comum, value is T não compila. Com reified, funciona como com uma classe comum: value is String, value is List<Int> (quase — com limitações para tipos parametrizados).

kotlin
inline fun <reified T> List<Any>.filterByType(): List<T> {
    return this.filter { it is T }.map { it as T }
}

val mixed = listOf("a", 1, "b", 2)
val strings = mixed.filterByType<String>() // ["a", "b"]
val ints = mixed.filterByType<Int>()    // [1, 2]

A função de extensão filterByType filtra uma lista, mantendo apenas elementos do tipo especificado. Sem reified, você teria que escrever filterByType<String>(list) com um parâmetro Class<String>. Com reified, a chamada é lida como uma operação natural em uma lista, melhorando a legibilidade das cadeias de processamento de dados.

De acordo com o Guia de Corrotinas Kotlin (JetBrains, 2025), verificações de tipo reified são usadas em launch e async para passar o tipo de resultado da corrotina, evitando a especificação explícita do tipo na maioria dos casos.

Reflexão com reified: criar instâncias e acessar Class

reified fornece acesso a T::class — uma referência a KClass, da qual se pode obter a Class Java através de .java. Isso abre possibilidades para criar instâncias através de reflexão, trabalhar com serializadores e obter anotações de classe em tempo de execução.

kotlin
inline fun <reified T> createInstance(): T =
    T::class.java.getDeclaredConstructor().newInstance()

// Usage
data class User(val name: String = "default")
val user = createInstance<User>()

// Serialization with Gson
inline fun <reified T> Gson.fromJson(json: String): T =
    this.fromJson(json, T::class.java)

// Getting annotations
inline fun <reified T> hasAnnotation<A>(): Boolean where A : Annotation =
    T::class.java.isAnnotationPresent(A::class.java)

O wrapper fromJson para Gson é um exemplo clássico de uso do reified em produção. Em vez de gson.fromJson(json, User::class.java), você pode escrever gson.fromJson<User>(json). Isso pode parecer uma melhoria menor, mas em um projeto com centenas de chamadas de serialização, o reified reduz significativamente o boilerplate e torna o código mais limpo.

Limitações do reified e alternativas

reified tem limitações. Primeiro — só funciona dentro de funções inline. Se uma função não puder ser inline (por exemplo, for recursiva ou muito grande), reified não está disponível. Segundo — reified não pode ser usado com funções suspend diretamente, apenas através de wrappers inline.

Terceiro — reified não funciona completamente com tipos parametrizados. Por exemplo, filterByType<List<String>>() pode dar resultados inesperados porque para tipos parametrizados, reified preserva apenas o tipo raw (List), sem os argumentos genéricos. Para verificação completa de tipos parametrizados, é necessária reflexão com TypeToken.

OperaçãoCom reifiedSem reified
value is T✅ Funciona❌ Erro de compilação
T::class✅ Funciona❌ Erro de compilação
List<String> is T⚠️ Apenas raw type❌ Erro
Criação de instância✅ Via reflexão❌ Precisa de Class<T>
Função suspend❌ Apenas via wrapper inline❌ Não aplicável

Para casos em que reified não está disponível, use o padrão com Class<T> explícito ou TypeToken de bibliotecas (por exemplo, Gson TypeToken ou Jackson TypeReference). Esta abordagem funciona em qualquer função, mas requer boilerplate e é menos conveniente.

Perguntas frequentes

Por que reified só funciona com funções inline?

O compilador substitui o parâmetro reified T pelo tipo concreto durante a inline do corpo da função. Se a função não for inline, o compilador não tem onde substituir o tipo — uma chamada de função genérica passa por um único bytecode onde T está apagado. Inline cria uma cópia de bytecode separada para cada tipo de argumento.

Pode-se declarar uma propriedade reified?

Não, reified só se aplica a parâmetros de função. Para propriedades, use o padrão inline fun <reified T> com valor de retorno, ou passe Class<T> explicitamente através de um construtor. Propriedades de extensão também não suportam reified.

Como reified funciona com tipos nullable?

reified suporta tipos nullable: reified T : Any (não nulo) e apenas reified T (pode ser nulo). Para tipos nullable, T::class retorna a classe para a versão não nula (String::class para String?). A verificação value is T leva em conta null: se T = String?, então null is T = true.

Há overhead com reified?

Mínimo. reified não usa reflexão — o compilador substitui o tipo concreto no estágio de inline. Em bytecode, isso é uma referência direta à classe (ldc + checkcast/invokevirtual). Não há overhead em comparação com passar Class<T> manualmente — ambas as abordagens geram bytecode idêntico.

Pode-se usar reified no desenvolvimento Android?

Sim, reified é usado ativamente no Android. Bundle.getParcelable<T>(), Intent.getSerializableExtra<T>(), viewModels<T>() do Android KTX — todas essas funções usam reified para evitar passar Class<T> explicitamente. De acordo com a Documentação Android do Google (2025), reified é recomendado para APIs genéricas onde o tipo é necessário em tempo de execução.

Resumo

  • reified — um modificador de parâmetro genérico para funções inline que preserva o tipo em tempo de execução
  • Type erasure — o mecanismo padrão de apagamento de tipos; reified o contorna através de inline
  • is/as — verificações e conversões de tipo funcionam com reified como com classes comuns
  • Referência de classe — T::class e T::class.java estão disponíveis para reflexão e serialização
  • Apenas inline — reified é impossível sem uma função inline devido ao mecanismo de substituição de tipo
  • Tipos parametrizados — reified não preserva argumentos genéricos (apenas raw type)
  • Aplicações — serialização Gson/Moshi, contêineres DI, verificações de tipo em coleções, Android KTX

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