Runtime component for full Kotlin reflection support, enabling inspection and manipulation of Kotlin classes, functions, properties, and types at runtime
—
Seamless bridge between Kotlin and Java reflection APIs, providing bidirectional conversion and access to JVM-specific features like accessibility control and type erasure.
Convert Kotlin reflection objects to their Java reflection equivalents.
/** Returns Java Field instance for property backing field, or null */
val KProperty<*>.javaField: Field?
/** Returns Java Method instance for property getter, or null */
val KProperty<*>.javaGetter: Method?
/** Returns Java Method instance for mutable property setter, or null */
val KMutableProperty<*>.javaSetter: Method?
/** Returns Java Method instance for function, or null if constructor */
val KFunction<*>.javaMethod: Method?
/** Returns Java Constructor instance for function, or null if not constructor */
val <T> KFunction<T>.javaConstructor: Constructor<T>?
/** Returns Java Type instance corresponding to this KType */
val KType.javaType: Type
/** Returns JVM name of the class represented by this KClass */
val KClass<*>.jvmName: StringUsage Examples:
class Person(val name: String) {
var age: Int = 0
fun greet(): String = "Hello, $name"
constructor(name: String, age: Int) : this(name) {
this.age = age
}
}
val personClass = Person::class
// Property to Java Field/Method mapping
val nameProperty = Person::name
val ageProperty = Person::age
val nameField = nameProperty.javaField
val nameGetter = nameProperty.javaGetter
val ageSetter = (ageProperty as? KMutableProperty<*>)?.javaSetter
println("Name field: ${nameField?.name}") // "name"
println("Name getter: ${nameGetter?.name}") // "getName"
println("Age setter: ${ageSetter?.name}") // "setAge"
// Function to Java Method mapping
val greetFunction = Person::greet
val javaMethod = greetFunction.javaMethod
println("Java method: ${javaMethod?.name}") // "greet"
// Constructor to Java Constructor mapping
val constructor = personClass.constructors.find { it.parameters.size == 3 }
val javaConstructor = constructor?.javaConstructor
println("Java constructor params: ${javaConstructor?.parameterCount}") // 2
// Type to Java Type mapping
val stringType = typeOf<String>()
val javaType = stringType.javaType
println("Java type: $javaType") // class java.lang.String
// Class JVM name
println("JVM name: ${personClass.jvmName}") // "Person"Convert Java reflection objects to their Kotlin reflection equivalents.
/** Returns KProperty instance for Java field, or null if not representable */
val Field.kotlinProperty: KProperty<*>?
/** Returns KFunction instance for Java method, or null if not representable */
val Method.kotlinFunction: KFunction<*>?
/** Returns KFunction instance for Java constructor, or null if not representable */
val <T : Any> Constructor<T>.kotlinFunction: KFunction<T>?Usage Examples:
class Sample {
val readOnlyProperty: String = "value"
var mutableProperty: Int = 42
fun sampleMethod(param: String): Int = param.length
}
val sampleClass = Sample::class.java
// Java Field to Kotlin Property
val javaFields = sampleClass.declaredFields
javaFields.forEach { field ->
val kotlinProperty = field.kotlinProperty
println("Field ${field.name} -> Kotlin property: ${kotlinProperty?.name}")
}
// Java Method to Kotlin Function
val javaMethods = sampleClass.declaredMethods
javaMethods.forEach { method ->
val kotlinFunction = method.kotlinFunction
if (kotlinFunction != null) {
println("Method ${method.name} -> Kotlin function: ${kotlinFunction.name}")
}
}
// Java Constructor to Kotlin Function
val javaConstructors = sampleClass.declaredConstructors
javaConstructors.forEach { constructor ->
val kotlinFunction = constructor.kotlinFunction
println("Constructor -> Kotlin function: ${kotlinFunction != null}")
}Access JVM-specific type information including type erasure.
/** Returns the KClass representing the runtime class this type is erased to on JVM */
val KType.jvmErasure: KClass<*>Usage Examples:
// Type erasure examples
val stringType = typeOf<String>()
val listType = typeOf<List<String>>()
val mapType = typeOf<Map<String, Int>>()
println("String erasure: ${stringType.jvmErasure}") // class kotlin.String
println("List erasure: ${listType.jvmErasure}") // interface kotlin.collections.List
println("Map erasure: ${mapType.jvmErasure}") // interface kotlin.collections.Map
// Complex generic type erasure
val complexType = typeOf<List<Map<String, List<Int>>>>()
println("Complex type erasure: ${complexType.jvmErasure}") // interface kotlin.collections.List
// Nullable type erasure
val nullableType = typeOf<String?>()
println("Nullable erasure: ${nullableType.jvmErasure}") // class kotlin.StringControl JVM access checks for reflective operations.
/**
* Provides a way to suppress JVM access checks for a callable
* For properties, affects all accessors (getter, setter, backing field)
*/
var KCallable<*>.isAccessible: BooleanUsage Examples:
class PrivateExample {
private val privateProperty: String = "secret"
private fun privateMethod(): String = "private result"
}
val example = PrivateExample()
val clazz = PrivateExample::class
// Access private property
val privateProperty = clazz.memberProperties.find { it.name == "privateProperty" }
if (privateProperty != null) {
try {
// This would normally throw IllegalCallableAccessException
val value = privateProperty.get(example)
} catch (e: Exception) {
println("Access denied: ${e.message}")
}
// Make accessible and try again
privateProperty.isAccessible = true
val value = privateProperty.get(example)
println("Private property value: $value") // "secret"
}
// Access private function
val privateFunction = clazz.memberFunctions.find { it.name == "privateMethod" }
if (privateFunction != null) {
privateFunction.isAccessible = true
val result = privateFunction.call(example)
println("Private method result: $result") // "private result"
}Access annotations through both Kotlin and Java reflection APIs.
/**
* Returns an annotation of the given type on this element
*/
inline fun <reified T : Annotation> KAnnotatedElement.findAnnotation(): T?
/**
* Returns true if this element is annotated with the given type
*/
inline fun <reified T : Annotation> KAnnotatedElement.hasAnnotation(): Boolean
/**
* Returns all annotations of the given type including repeated annotations
*/
inline fun <reified T : Annotation> KAnnotatedElement.findAnnotations(): List<T>Usage Examples:
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
annotation class MyAnnotation(val value: String)
@Target(AnnotationTarget.FUNCTION)
annotation class Deprecated(val message: String)
@MyAnnotation("class-level")
class AnnotatedClass {
@MyAnnotation("property-level")
val annotatedProperty: String = "value"
@MyAnnotation("function-level")
@Deprecated("This method is deprecated")
fun annotatedMethod(): String = "result"
}
val clazz = AnnotatedClass::class
// Check class annotations
val classAnnotation = clazz.findAnnotation<MyAnnotation>()
println("Class annotation: ${classAnnotation?.value}") // "class-level"
val hasAnnotation = clazz.hasAnnotation<MyAnnotation>()
println("Class has annotation: $hasAnnotation") // true
// Check property annotations
val property = clazz.memberProperties.find { it.name == "annotatedProperty" }
val propertyAnnotation = property?.findAnnotation<MyAnnotation>()
println("Property annotation: ${propertyAnnotation?.value}") // "property-level"
// Check function annotations
val function = clazz.memberFunctions.find { it.name == "annotatedMethod" }
val functionAnnotations = function?.findAnnotations<MyAnnotation>()
println("Function annotations: ${functionAnnotations?.size}") // 1
val deprecatedAnnotation = function?.findAnnotation<Deprecated>()
println("Deprecated message: ${deprecatedAnnotation?.message}") // "This method is deprecated"Handle JVM reflection specific exceptions.
/**
* Thrown when call is invoked on a callable that is not accessible
*/
class IllegalCallableAccessException(cause: IllegalAccessException) : Exception
/**
* Thrown when getDelegate is invoked on a non-accessible property
*/
class IllegalPropertyDelegateAccessException(cause: IllegalAccessException) : Exception
/**
* Thrown when introspecting a property that no longer exists
*/
class NoSuchPropertyException(cause: Exception? = null) : ExceptionUsage Examples:
class ExampleClass {
private val privateProperty: String = "private"
}
val clazz = ExampleClass::class
val instance = ExampleClass()
// Attempt to access private property without making it accessible
val privateProperty = clazz.memberProperties.find { it.name == "privateProperty" }
try {
val value = privateProperty?.get(instance)
} catch (e: IllegalCallableAccessException) {
println("Access exception: ${e.message}")
println("Caused by: ${e.cause}")
// Make accessible and retry
privateProperty?.isAccessible = true
val value = privateProperty.get(instance)
println("Successfully accessed: $value")
}
### Lambda Reflection
Experimental API for reflecting on lambda expressions and function instances.
```kotlin { .api }
/**
* Experimental API to get KFunction instance for compiled lambda or function expression
* Note: call() and callBy() are not currently supported
*/
@ExperimentalReflectionOnLambdas
fun <R> Function<R>.reflect(): KFunction<R>?
/**
* Annotation marking experimental lambda reflection API
*/
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalReflectionOnLambdasUsage Examples:
@OptIn(ExperimentalReflectionOnLambdas::class)
fun demonstrateLambdaReflection() {
val lambda: (String) -> Int = { it.length }
// Reflect on lambda
val reflected = lambda.reflect()
if (reflected != null) {
println("Lambda name: ${reflected.name}")
println("Parameters: ${reflected.parameters.size}")
println("Return type: ${reflected.returnType}")
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-reflect