kotlinadvanced
Annotations and Runtime Reflection
Work with Kotlin annotations and reflection: custom annotations, property inspection, and annotation processing.
kotlinPress ⌘/Ctrl + Shift + C to copy
import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty
import kotlin.reflect.full.*
import kotlin.reflect.jvm.isAccessible
// Custom annotations
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class JsonField(val name: String = "")
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class Required
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class MaxLength(val value: Int)
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class Entity(val tableName: String = "")
// Annotated data class
@Entity(tableName = "users")
data class User(
@JsonField("user_id")
val id: Int,
@Required
@MaxLength(50)
@JsonField("user_name")
val name: String,
@Required
@JsonField
val email: String,
@MaxLength(500)
val bio: String? = null
)
// Reflection-based JSON serializer
fun Any.toJsonMap(): Map<String, Any?> {
val kClass = this::class
return kClass.memberProperties.associate { prop ->
prop.isAccessible = true
val jsonField = prop.findAnnotation<JsonField>()
val key = if (jsonField != null && jsonField.name.isNotEmpty()) {
jsonField.name
} else {
prop.name
}
key to prop.getter.call(this)
}
}
// Reflection-based validator
fun Any.validate(): List<String> {
val errors = mutableListOf<String>()
val kClass = this::class
for (prop in kClass.memberProperties) {
prop.isAccessible = true
val value = prop.getter.call(this)
// Check @Required
if (prop.findAnnotation<Required>() != null) {
if (value == null || (value is String && value.isBlank())) {
errors.add("${prop.name} is required")
}
}
// Check @MaxLength
prop.findAnnotation<MaxLength>()?.let { maxLen ->
if (value is String && value.length > maxLen.value) {
errors.add("${prop.name} exceeds max length of ${maxLen.value}")
}
}
}
return errors
}
// Reflection utilities
fun <T : Any> inspectClass(kClass: KClass<T>) {
println("=== ${kClass.simpleName} ===")
// Class annotations
kClass.annotations.forEach { ann ->
println(" @${ann.annotationClass.simpleName}")
if (ann is Entity) println(" table: ${ann.tableName}")
}
// Properties
println(" Properties:")
kClass.memberProperties.forEach { prop ->
val annotations = prop.annotations.map { it.annotationClass.simpleName }
val mutable = if (prop is KMutableProperty<*>) "var" else "val"
println(" $mutable ${prop.name}: ${prop.returnType} $annotations")
}
// Constructors
println(" Constructors:")
kClass.constructors.forEach { ctor ->
val params = ctor.parameters.map { "${it.name}: ${it.type}" }
println(" (${params.joinToString(", ")})")
}
}
// Dynamic object creation
fun <T : Any> createInstance(kClass: KClass<T>, args: Map<String, Any?>): T {
val ctor = kClass.primaryConstructor
?: throw IllegalArgumentException("No primary constructor")
val params = ctor.parameters.associateWith { param ->
args[param.name] ?: if (param.isOptional) null
else throw IllegalArgumentException("Missing: ${param.name}")
}.filterValues { it != null || true }
return ctor.callBy(params.filter { !it.key.isOptional || it.value != null })
}
fun main() {
val user = User(1, "Alice", "alice@test.com", "Developer")
// Serialize
println("JSON map: ${user.toJsonMap()}")
// Validate
val valid = user.validate()
println("\nValidation: ${if (valid.isEmpty()) "PASS" else valid}")
val invalid = User(2, "", "", "x".repeat(600))
println("Invalid: ${invalid.validate()}")
// Inspect
println()
inspectClass(User::class)
// Dynamic creation
val dynamic = createInstance(User::class, mapOf(
"id" to 3,
"name" to "Bob",
"email" to "bob@test.com"
))
println("\nDynamic: $dynamic")
}Use Cases
- Custom annotation-driven validation
- Reflection-based serialization
- Dynamic object creation and inspection
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
javaadvanced
Custom Annotations and Reflection
Create and process custom annotations with reflection: field validation, auto-logging, and metadata.
Best for: Custom validation frameworks
#java#annotations
javaadvanced
Reflection Utilities — Inspect and Invoke
Inspect classes at runtime: list fields/methods, invoke methods, get annotations, and create instances.
Best for: Framework and library development
#java#reflection
kotlinbeginner
Null Safety — Elvis, Safe Call, and let
Master Kotlin null safety: safe calls, Elvis operator, let/also scoping, and smart casts.
Best for: Safe navigation through nullable chains
#kotlin#null-safety
kotlinbeginner
Data Classes — Copy, Destructure, and Equals
Use data classes for immutable models: auto-generated equals, hashCode, copy, and destructuring.
Best for: Immutable domain models and DTOs
#kotlin#data-class