Validação e mapeamento baseados em reflexão
Crie um validador simples ou um mapeador de objetos usando reflexão orientada por anotações.
Validação e mapeamento baseados em reflexão é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.
O que este padrão resolve
A validação baseada em reflexão lê anotações das propriedades de uma classe em tempo de execução e aplica regras de validação automaticamente — sem verificações manuais para cada campo. A mesma técnica é usada por mapeadores ORM que convertem objetos em linhas do banco de dados e vice-versa.
A anotação Validate
Defina uma anotação mantida em tempo de execução e direcionada a propriedades:
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.PROPERTY)
annotation class Validate(
val minLength: Int = 0,
val maxLength: Int = Int.MAX_VALUE,
val pattern: String = ""
)Anotação de uma classe de dados
Aplique @Validate às propriedades da classe de dados. O validador as examinará em tempo de execução:
data class UserForm(
@Validate(minLength = 2, maxLength = 50) val name: String,
@Validate(pattern = "^[\\w.]+@[\\w]+\\.[a-z]{2,}$") val email: String,
@Validate(minLength = 8) val password: String
)A função validadora
Use KClass.declaredMemberProperties para percorrer as propriedades, localizar as anotações e coletar os erros:
fun validate(obj: Any): List<String> {
val errors = mutableListOf<String>()
for (prop in obj::class.declaredMemberProperties) {
val ann = prop.findAnnotation<Validate>() ?: continue
val value = (prop as KProperty1<Any, *>).get(obj)?.toString() ?: ""
if (value.length < ann.minLength) errors += "${prop.name}: too short"
if (value.length > ann.maxLength) errors += "${prop.name}: too long"
if (ann.pattern.isNotEmpty() && !value.matches(Regex(ann.pattern)))
errors += "${prop.name}: invalid format"
}
return errors
}Executando o validador
Chame validate() com qualquer objeto anotado. A função retorna uma lista de mensagens de erro; uma lista vazia significa que o objeto é válido:
val form = UserForm("A", "not-an-email", "short")
val errors = validate(form)
errors.forEach(::println)
// name: too short
// email: invalid format
// password: too shortMapeamento de objeto para mapa com @Column
Outro padrão de reflexão mapeia um objeto para um Map usando uma anotação @Column para fornecer os nomes das colunas:
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.PROPERTY)
annotation class Column(val name: String)
fun toMap(obj: Any): Map<String, Any?> =
obj::class.declaredMemberProperties
.mapNotNull { prop ->
val col = prop.findAnnotation<Column>() ?: return@mapNotNull null
col.name to (prop as KProperty1<Any, *>).get(obj)
}.toMap()Usando o mapeador
Anote a classe de dados e chame toMap() para obter um mapa indexado por colunas, pronto para uma instrução INSERT:
data class User(
@Column("user_name") val name: String,
@Column("user_email") val email: String
)
val user = User("Alice", "alice@example.com")
println(toMap(user))
// {user_name=Alice, user_email=alice@example.com}Armazenando em cache os resultados da reflexão
As varreduras de reflexão são dispendiosas. Armazene em cache, na inicialização, o mapeamento de propriedades para anotações usando um ConcurrentHashMap indexado por KClass:
val cache = ConcurrentHashMap<KClass<*>, List<Pair<KProperty1<Any,*>, Column>>>()
fun columnsOf(klass: KClass<*>) = cache.getOrPut(klass) {
klass.declaredMemberProperties
.mapNotNull { p ->
p.findAnnotation<Column>()?.let { (p as KProperty1<Any,*>) to it }
}
}Combinando validação e mapeamento
Você pode empilhar anotações em uma única propriedade e processar cada uma de forma independente. Primeiro valide e depois mapeie — ou faça ambas as operações em uma única passagem, coletando cada tipo de anotação:
data class Product(
@Validate(minLength = 1) @Column("product_name") val name: String,
@Column("price") val price: Double
)Limitações
A validação baseada em reflexão é poderosa, mas envolve algumas concessões: acrescenta sobrecarga em tempo de execução, depende da retenção das anotações e não consegue detectar erros em tempo de compilação. Para uma validação crítica para o desempenho ou segura em tempo de compilação, considere código gerado pelo KSP.
Quando usar este padrão
A validação baseada em reflexão é especialmente útil em código de estruturas que precisa lidar com classes arbitrárias definidas pelo usuário: mapeadores objeto-relacional, serializadores, validadores de formulários e vinculadores de configuração. O código da aplicação que controla seus próprios tipos deve preferir a validação explícita, por sua velocidade e clareza.
Verificação rápida
Qual política de retenção de anotações é necessária para que uma anotação de validação possa ser lida em tempo de execução?
Recapitulação: validação e mapeamento baseados em reflexão
Principais conclusões:
- Declare anotações mantidas em tempo de execução e direcionadas a propriedades
- Use
declaredMemberProperties+findAnnotationpara conduzir a validação ou o mapeamento - Armazene os resultados em cache por
KClasspara evitar a sobrecarga de reflexão repetida - Empilhe várias anotações em uma propriedade para combinar comportamentos
- Considere o KSP para alternativas em tempo de compilação em trechos críticos para o desempenho
Aprenda Kotlin com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 51
- Aulas
- 203
Perguntas Frequentes
A aula “Validação e mapeamento baseados em reflexão” é grátis?
Sim — o texto completo de “Validação e mapeamento baseados em reflexão” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.
O que vou aprender em “Validação e mapeamento baseados em reflexão”?
Crie um validador simples ou um mapeador de objetos usando reflexão orientada por anotações. Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Kotlin Academy?
Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Validação e mapeamento baseados em reflexão”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Kotlin Academy?
Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Reflexão no Kotlin: KClass, KFunction, KProperty
- Criando e direcionando anotações personalizadas
- Lendo anotações em tempo de execução
- Validação e mapeamento baseados em reflexão