How do you use reflection in Kotlin?
sobes.tech AI
Answer from AI
Reflection in Kotlin is used for inspecting and manipulating code structures at runtime.
Typical use cases:
-
Annotations: Reading and processing annotations applied to classes, functions, properties.
// Defining an annotation annotation class ApiEndpoint(val path: String) // Applying the annotation @ApiEndpoint("/users") class UserController // Reading the annotation at runtime fun processAnnotations() { val controllerClass = UserController::class val annotation = controllerClass.annotations.find { it is ApiEndpoint } as? ApiEndpoint println(annotation?.path) // Will output "/users" } -
Dynamic instantiation: Creating class objects by name known only at runtime.
// Suppose we have a class class DynamicClass(val name: String) fun createInstanceDynamically(className: String) { try { val kClass = Class.forName(className).kotlin val constructor = kClass.constructors.find { it.parameters.size == 1 && it.parameters.first().type.classifier == String::class } val instance = constructor?.call("Dynamic object") as? DynamicClass println(instance?.name) } catch (e: ClassNotFoundException) { println("Class $className not found") } } // Call // createInstanceDynamically("DynamicClass") // Will output "Dynamic object" -
Accessing properties and invoking functions by name: Getting and setting property values, calling object methods when names are known at runtime.
data class User(var name: String, val age: Int) fun manipulateObject(obj: Any, propertyName: String, newName: String) { val kClass = obj::class val property = kClass.members.find { it.name == propertyName } as? kotlin.reflect.KMutableProperty<*> if (property != null) { try { property.setter.call(obj, newName) println("Property $propertyName successfully changed to $newName") } catch (e: Exception) { println("Error changing property: ${e.message}") } } else { println("Property $propertyName not found or is not mutable") } } // Call // val user = User("Initial Name", 30) // manipulateObject(user, "name", "New Name") // Will output "Property name successfully changed to New Name" // manipulateObject(user, "age", 31) // Will output "Property age not found or is not mutable" -
Serialization/deserialization: Libraries like Jackson, Gson use reflection for mapping data to objects and back.
-
Testing: For creating mocks or inspecting private members during testing.
-
Frameworks and libraries: Many frameworks (e.g., Spring, Ktor) use reflection for dependency injection, routing, and annotation processing.
It is important to note that using reflection can reduce performance and complicate static code analysis. Therefore, it should be used cautiously and only when other approaches (e.g., static typing, code generation) are not applicable. Kotlin provides reflection APIs in the kotlin.reflect package.