Skip to content

Instantly share code, notes, and snippets.

@begomez
Last active July 30, 2020 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save begomez/5858179c6e8eafd214606efd05e1fd79 to your computer and use it in GitHub Desktop.
Save begomez/5858179c6e8eafd214606efd05e1fd79 to your computer and use it in GitHub Desktop.
Reflection in Kotlin
package com.bgomez.recipapp
import kotlin.reflect.*
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.memberProperties
/**
* Custom annotation that can be applied on class props
*/
@Target(AnnotationTarget.PROPERTY)
annotation class MyCustomAnnotation(val value : String)
/**
* Data class for Person.
* Applies annotations on some properties
*
* Created by bernatgomez on July,2020
*/
data class Person(
@MyCustomAnnotation(value="Some annotation value goes here...") val personName : String,
val personAge : Int) {
fun displayAgeInformation(threshold : Int) : Unit {
println("Is $personName an adult? ${isAdult(threshold)}")
}
fun isAdult(threshold: Int) : Boolean = this.personAge >= threshold
fun paramsExample(num : Int, str : String, p : Person) : Unit {}
}
/**
* Execution entry point
*/
fun main(args : Array<String>) {
accessClass()
accessConstructors()
accessCallable()
accessFunction()
accessFunctionParameters()
accessProperty()
accessAnnotations()
}
fun accessClass() {
val p = Person("John", 20)
//XXX: Kotlin reflection
val pClazz0 : KClass<Person> = Person::class
val pClazz1 : KClass<Person> = p.javaClass.kotlin
//XXX: Java reflection
val pClazz2 : Class<Person> = Person::class.java
println("Person class props-------------------------------------------------------------------")
println(pClazz0.qualifiedName)
println(pClazz1.qualifiedName)
println(pClazz2.name)
//XXX: switch from one API to another
println(pClazz2.kotlin.qualifiedName)
}
fun accessConstructors() {
val clazz : KClass<Person> = Person::class
val construcs : Collection<KFunction<Person>> = clazz.constructors
println("Person constructors------------------------------------------------------------------")
construcs.forEach {construc ->
println("Constructor $construc")
}
}
fun accessCallable() {
val p = Person("John", 20)
//XXX: member ref to fun, function will be called, params needed
val mCall : KCallable<Unit> = p::displayAgeInformation
//XXX: ok, params match
mCall.call(THRESHOLD)
//FIXME: ko, no match
//mCall.call("21")
//FIXME: ko, params required
//mCall.call()
//XXX: member ref to prop, accessor will be called, NO Params needed
var pCall : KCallable<Int> = p::personAge
println("${p.personName}'s age is ${pCall.call()}")
//XXX: member ref directly through class
pCall = Person::personAge
println("${p.personName}'s age is ${pCall.call(p)}")
}
fun accessFunction() {
val p = Person("John", 20)
println("Function info------------------------------------------------------------------------")
val mFun : KFunction<Boolean> = p::isAdult
println("infix ? ${mFun.isInfix}")
println("inline ? ${mFun.isInline}")
println("suspend? ${mFun.isSuspend}")
println("open ? ${mFun.isOpen}")
val result = mFun.call(THRESHOLD)
println("Result is $result of type ${result.javaClass}")
}
fun accessFunctionParameters() {
val p = Person("John", 20)
val mFun : KFunction<Unit> = p::paramsExample
val mParams : List<KParameter> = mFun.parameters
mParams.forEach { param ->
println("Param ${param.name} of type ${param.type.toString()}")
}
}
fun accessProperty() {
val mGlobalProp : KMutableProperty0<Int> = ::THRESHOLD
println("global var has value ${mGlobalProp.get()}")
mGlobalProp.set(21)
println("global var has value ${mGlobalProp.get()}")
val p1 = Person("John", 40)
val p2 = Person("Jane", 50)
val mProp : KProperty1<Person, Int> = Person::personAge
println("${p1.personName}'s age is ${mProp.get(p1)}")
println("${p2.personName}'s age is ${mProp.get(p2)}")
val mProps : Collection<KProperty1<Person, *>> = p1.javaClass.kotlin.memberProperties
println("Class props--------------------------------------------------------------------------")
mProps.forEach { prop ->
println(prop.name)
}
}
fun accessAnnotations() {
val p = Person("Joe", 60)
val mProps : Collection<KProperty1<Person, *>> = p.javaClass.kotlin.memberProperties
println("Annotations--------------------------------------------------------------------------")
for (mProp in mProps) {
val mCustomAnnotation : MyCustomAnnotation? = mProp.findAnnotation<MyCustomAnnotation>()
mCustomAnnotation?.let {
println(it.annotationClass )
println(it.value)
}
}
}
var THRESHOLD = 18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment