How do you read and write a property's value reflectively using KProperty.get() and the setter, including for member properties?
answer
- KProperty1.get(receiver) reads a member property
- var -> KMutableProperty -> set(receiver, value)
- getter/setter are KFunctions: .call(receiver, value)
- Private: isAccessible = true on prop or accessor
- KProperty0 = no receiver (top-level/object)
basics
~20 sGet a KProperty for the field. To read, call get() (passing the receiver object for member properties). To write, the property must be a var (KMutableProperty); call its setter via .setter.call(receiver, newValue) or .set(receiver, newValue).
solid answer
~30 sA read-only property is a KProperty (KProperty0/1/2 by receiver count); a var is a KMutableProperty exposing set(). For a member property you use KProperty1<T, V>: prop.get(instance) reads, and if it's a KMutableProperty1<T, V> then prop.set(instance, value) writes. You can also go through the accessors directly: prop.getter.call(instance) and prop.setter.call(instance, value) — the getter/setter are themselves KFunctions. Top-level / object properties use KProperty0 (no receiver): prop.get() / prop.set(value). Reading a val reflectively is fine; you can only set() through KMutableProperty. Private or non-accessible backing requires isAccessible = true on the property (or its accessor). kotlin-reflect must be present for member property reflection.
code
kotlin · 13 linesimport kotlin.reflect.KMutableProperty1
import kotlin.reflect.full.memberProperties
class Box(var n: Int)
fun main() {
val b = Box(1)
val p = Box::class.memberProperties.first { it.name == "n" } as KMutableProperty1<Box, Int>
println(p.get(b)) // 1
p.set(b, 7)
p.setter.call(b, 9) // via setter KFunction
println(b.n) // 9
}go deeper
Reads a property with get(receiver) and knows var is needed to write.
Casts to KMutableProperty1, uses set()/setter.call(), and handles top-level vs member receiver differences.
Explains getter/setter as KFunctions, isAccessible scope, and that get() invokes any custom accessor (not the raw field).
Builds generic property-mapping/copy utilities, weighs reflective property access cost, and reasons about backing-field vs accessor semantics.
## Property reflection types Kotlin models properties (not just fields) reflectively: - `KProperty0<V>` — no receiver (top-level/object property): `get()`. - `KProperty1<T, V>` — one receiver (member): `get(receiver)`. - `KProperty2<D, E, V>` — two receivers (member extension). - The **mutable** variants `KMutableProperty0/1/2` add `set(...)`. ## Reading ```kotlin import kotlin.reflect.full.memberProperties class Box(var n: Int) val prop = Box::class.memberProperties.first { it.name == "n" } val value = prop.get(Box(5)) // 5 (KProperty1.get(receiver)) ``` You can equivalently call the **getter** KFunction: `prop.getter.call(Box(5))`. ## Writing Only a `var` is mutable. Cast / check for `KMutableProperty1`: ```kotlin import kotlin.reflect.KMutableProperty1 val b = Box(0) val mp = prop as KMutableProperty1<Box, Int> mp.set(b, 42) // direct setter // or: mp.setter.call(b, 99) // via setter KFunction ``` The **setter** is a `KFunction`; `setter.call(receiver, value)` is positional just like any reflective call. ## Accessibility Private properties (or those with private accessors) throw `IllegalCallableAccessException` until you set `isAccessible = true`: ```kotlin prop.isAccessible = true // on the property // or prop.getter.isAccessible = true / prop.setter.isAccessible = true ``` ## Notes - A `val` exposes no `set()` — attempting to cast to `KMutableProperty` and set is a compile/runtime mismatch. - For top-level (`KProperty0`) there is no receiver argument. - `prop.getter`/`prop.setter` are useful when you want a uniform `KFunction` invocation path or to flip `isAccessible` on the accessor specifically. - Requires **kotlin-reflect** for member properties.
- Why can't you set() a val reflectively?A val has no setter, so reflection exposes it only as a KProperty (not KMutableProperty); there is no set() to call. You can still read it with get().
- What's the difference between prop.get(x) and prop.getter.call(x)?They are equivalent for reading; get() is the typed convenience method while getter.call() routes through the accessor as a generic KFunction (handy for flipping isAccessible on the accessor).
saying these in an interview costs you the question
- Trying to set() a val / KProperty that isn't mutable
- Omitting the receiver for a KProperty1.get()
- Forgetting isAccessible for private property reads
- Confusing KProperty0 (no receiver) with KProperty1
- Assuming get() bypasses a custom getter — it invokes it