Retrieve default parameter value via reflection

Given this example:

data class Example(val abc: Int = 100)

How would I be able to tell the default value of abc is 100 via reflection? Assume I have the KParameter instance already.

1 Like

The default value is not actually a property of the parameter. If you use default values the compiler will generate overloaded methods and constructors. The default value is part of the body of these methods and constructors.

2 Likes

Hello, have you found any solution?

I believe what @jstuyts says remains true: it’s not possible to retrieve, unfortunately.

Hey, so it is not as impossible as it may seem, though it is certainly digging deeper into the depths of Kotlin reflection than I would prefer to be :smile:

// Lets say I have a simple data class
data class Testerino(val a: Int = 100, val b: String?, val c: Boolean)

// and a main function
fun main() {
  // upon reflection 
  val clazz = Testerino::class
  // we can retrieve the primary constructor
  val cons = clazz.primaryConstructor
  // here we get a little wild
  val values = cons
    ?.parameters
    ?.filterNot { it.isOptional }
    ?.associate { it to forgiveMeFather(it) } 
    ?: error("Should not get here")
  // given our map of mandatory parameters, we call our constructor with said map
  val test = cons.callBy(values)
  println(test)
  // outputs Testerino(a=100, b=test, c=false)
}

// And finally my type handler
private fun forgiveMeFather(param: KParameter): Any = when (param.type.classifier) {
  String::class -> "test"
  Boolean::class -> false
  else -> error("Unsupported Type")
}

The real magic happens in the values assignment. Parameters that have a default value are
considered “optional”. This means, we can filterNot for it.isOptional
to retrieve all parameters that don’t have a default parameter.

At this point, we can take our mandatory parameters and give them a
value required for construction via the forgiveMeFather function.

This is the real limitation of this approach. You need to know how to
handle every type you are going to encounter. Perhaps this will
not be feasible for certain cases, but this is a pretty niche case,
so hopefully you are only dealing with a subset of types to begin with.

4 Likes