skip to content

Kotlin Reflection (kotlin-reflect)

Inspecting and invoking Kotlin declarations at runtime through the KClass and KCallable hierarchy. It is powerful, it is slow, and it needs an extra artifact — three facts an interviewer expects together.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

explore

questions

page 1 of 2

What is a callable reference in Kotlin, and how do you write a reference to a top-level function, a member function, and a property?

level: juniorimportance: must knowfreq 70%

answer

  1. :: = "point at", don't call
  2. ::fn top-level, Class::m unbound, obj::m bound
  3. String::length has type (String) -> Int
  4. Result is KFunction/KProperty (a KCallable)
  5. Replaces trivial lambdas in map/filter

basics

~10 s

A callable reference points at an existing function or property by name using the :: operator, so you can pass it around instead of writing a lambda. Example: list.map(String::length).

solid answer

~30 s

A callable reference uses the :: operator to grab an existing declaration as a value instead of calling it. ::topLevelFun references a top-level function; String::length references a member (here a property) on the class; obj::method binds to a specific instance. The result is a function-typed object (KFunction/KProperty) you can pass where a lambda is expected, e.g. names.map(String::uppercase) or list.filter(::isValid). It avoids the boilerplate lambda { it.uppercase() } and reads more declaratively. The reference's type matches the underlying signature, so String::length has type (String) -> Int. References also implement KCallable, so they double as reflection handles.

code

kotlin · 6 lines
kotlin
fun shout(s: String) = s.uppercase() + "!"
val words = listOf("hi", "yo")

val a = words.map(::shout)        // top-level fun ref
val b = words.map(String::uppercase) // unbound member ref, (String)->String
val c: () -> Int = "hello"::length   // bound member ref

go deeper

for a junior

Knows :: makes a reference, can use String::length in map and pass ::topLevelFun where a lambda is expected.

for a middle

Distinguishes unbound vs bound and states the resulting function type precisely.

for a senior

Connects references to KFunction/KProperty/KCallable and knows the stdlib-vs-kotlin-reflect line for plain use vs introspection.

for a principal

Frames references as the bridge between Kotlin's functional-value model and its reflection model and reasons about API design implications of accepting references.

## What a callable reference is A **callable reference** turns an existing function or property into a **value** you can pass around, instead of *calling* it. You create one with the **`::` operator**. Think of it as "point at this declaration" rather than "invoke this declaration". ## The three common forms ```kotlin // 1. Top-level (or local) function reference — nothing before :: fun isOdd(x: Int) = x % 2 == 1 val refs = listOf(1, 2, 3).filter(::isOdd) // ::isOdd has type (Int) -> Boolean // 2. Member reference on a CLASS — ClassName::member (unbound) val lengths = listOf("a", "bb").map(String::length) // (String) -> Int // 3. Member reference on an INSTANCE — instance::member (bound) val s = "hello" val getLen: () -> Int = s::length // already bound to s, no String param ``` ## Why use them - **Less boilerplate** than a lambda: `String::uppercase` vs `{ s -> s.uppercase() }`. - **Declarative**: the name documents intent. - They satisfy any **function type** parameter (`(T) -> R`), so they slot into `map`, `filter`, `let`, etc. ## What you actually get back The `::` expression produces an object implementing **`KFunction`** (for functions) or **`KProperty`** (for properties), both of which extend **`KCallable`**. So a reference is simultaneously: - usable as a **function** (you can `invoke()` / call it), and - a **reflection handle** (it has `.name`, `.parameters`, etc.). Basic function-as-value usage (calling it) works with only the standard library. Deeper reflection on it (reading `.name`, `.parameters`) needs the **`kotlin-reflect`** artifact at runtime. ## Quick mental model `obj.method()` = call now. `obj::method` = a thing I can call later.

  • What type does String::length have?
    (String) -> Int — it's an unbound reference, so the receiver becomes the first parameter.
  • Do you need kotlin-reflect just to pass String::uppercase to map?
    No. Using a reference as a plain function value works with the stdlib alone; kotlin-reflect is only needed to introspect it (read name, parameters, etc.).

A lambda is writing a sticky note 'go do X'; a callable reference is just handing someone the phone number of the function that already does X.

saying these in an interview costs you the question

  • Confusing :: with calling — saying obj::method() runs the method now
  • Thinking ::fn returns the function's return value instead of a function object
  • Believing every callable reference always requires kotlin-reflect
  • Not knowing the receiver becomes a parameter in an unbound reference

context

open as a page

How do you invoke a function at runtime using Kotlin reflection's KFunction.call(), and what arguments must you pass?

level: juniorimportance: must knowfreq 55%

basics

~20 s

You get a KFunction (for example from ::myFunc or a KClass member) and call its call(...) method, passing the arguments in the same order the function declares them. For a member function, the first argument is the receiver object.

open as a page

In Kotlin, what does the built-in standard library give you for reflection out of the box, and when do you need to add the kotlin-reflect dependency?

level: juniorimportance: must knowfreq 55%

basics

~10 s

Basic things like ::class work without extra setup. Richer reflection (reading properties, functions, parameters, supertypes) needs the separate kotlin-reflect library added to your build.

open as a page

How do you obtain a KClass in Kotlin, and what is the difference between writing `instance::class` and `String::class`?

level: juniorimportance: must knowfreq 70%

basics

~20 s

Use ::class. On a value like x::class you get the real runtime type of that object. On a type name like String::class you get that exact declared class. Both give a KClass, Kotlin's reflection handle for a class.

open as a page

In Kotlin, how do you convert a KClass to a java.lang.Class and back again? Name the exact extension properties.

level: juniorimportance: must knowfreq 70%

basics

~10 s

Kotlin has two class objects. Use the .java property to turn a Kotlin class into a Java Class, and the .kotlin property to turn a Java Class back into a Kotlin one.

open as a page

What is KType in Kotlin reflection, and what does it represent that a KClass cannot?

level: juniorimportance: must knowfreq 55%

basics

~20 s

KType describes a full type used in code, like List<String>?. It knows the type arguments and whether the type can be null. A KClass only knows the bare class (List), not its arguments or nullability.

open as a page

What does the kotlin-reflect library let you inspect at runtime that plain java.lang.reflect cannot?

level: juniorimportance: must knowfreq 55%

basics

~10 s

Kotlin reflection can see Kotlin-only details like whether a type is nullable, default parameter values, properties, and suspend functions. Plain Java reflection only sees what Java understands and misses these.

open as a page

Explain the difference between a bound and an unbound callable reference, including how their function types differ.

level: middleimportance: must knowfreq 60%

basics

~10 s

Unbound references name a member on a class (Class::m) and take the receiver as a parameter. Bound references fix a specific object (obj::m), so the receiver is baked in and not a parameter.

open as a page

When should you use KFunction.callBy() instead of call(), and how do you build its KParameter map to honor default arguments?

level: middleimportance: must knowfreq 45%

basics

~20 s

Use callBy() when the function has default parameters and you only want to supply some of them. You pass a Map<KParameter, Any?> with entries only for the parameters you provide; omitted ones with defaults are filled in automatically.

open as a page

Why do JVM frameworks like Jackson, Spring, or JPA require you to pass MyType::class.java instead of MyType::class?

level: middleimportance: must knowfreq 65%

basics

~10 s

Those frameworks are written in Java and only understand Java's Class type. Kotlin's KClass is a different type, so you convert it with .java before handing it over.

open as a page

How does typeOf<T>() work, and why is a reified type parameter usually involved?

level: middleimportance: must knowfreq 50%

basics

~20 s

typeOf<T>() returns the KType for whatever type you put in the angle brackets. To pass a generic type variable T into it from your own function, T must be reified, which only works in an inline function.

open as a page

What is KCallable in Kotlin reflection, and how do KFunction and KProperty relate to it?

level: juniorimportance: should knowfreq 35%

basics

~10 s

KCallable is the common reflection type for things you can call or read: functions and properties. KFunction represents a function, and KProperty represents a property; both are kinds of KCallable.

open as a page

Show how constructor references (::ClassName) and mutable-property references work, including using a property reference to both read and write a field reflectively.

level: middleimportance: should knowfreq 35%

basics

~10 s

::ClassName references a constructor and acts like a factory function. A property reference to a var lets you read it with get and change it with set, because it is a KMutableProperty.

open as a page

How do you read and write a property's value reflectively using KProperty.get() and the setter, including for member properties?

level: middleimportance: should knowfreq 40%

basics

~20 s

Get 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).

open as a page

You only need to check an object's type and read its simple name. How do you do that without pulling in kotlin-reflect, and what exactly are the limits of ::class on stdlib alone?

level: middleimportance: should knowfreq 40%

basics

~10 s

Use ::class with simpleName/qualifiedName, isInstance, or the is operator — these work without kotlin-reflect. You only hit the wall when you want members, constructors, or supertypes.

open as a page

What are the concrete costs of depending on kotlin-reflect — binary size, startup, and runtime — and how do you reason about them?

level: middleimportance: should knowfreq 45%

basics

~10 s

kotlin-reflect adds several megabytes to your app, makes startup a bit slower the first time you reflect, and each reflective lookup is much slower than a direct call. Use it sparingly and cache results.

open as a page

Explain the difference between KProperty0, KProperty1, and KProperty2, and where KMutableProperty fits in.

level: middleimportance: should knowfreq 40%

basics

~10 s

The number means how many receivers you must pass to read the property. KProperty0 needs none, KProperty1 needs one (the object), KProperty2 needs two. KMutableProperty versions also let you write the value.

open as a page

Compare members, functions, and declaredMemberProperties on a KClass. What does each return and how do they differ regarding inheritance?

level: middleimportance: should knowfreq 38%

basics

~10 s

members lists all callable members (functions and properties), including inherited ones. functions lists functions including inherited. declaredMemberProperties lists only properties declared in that class, not inherited ones.

open as a page

What does `KClass.objectInstance` return, and how does it behave for objects vs regular classes?

level: middleimportance: should knowfreq 45%

basics

~10 s

objectInstance gives you the single shared instance of a Kotlin object (a singleton). If the KClass is for an object declaration it returns that instance; for an ordinary class it returns null.

open as a page

What does `KClass.sealedSubclasses` give you, and what are its limitations for non-sealed or deeply nested hierarchies?

level: middleimportance: should knowfreq 40%

basics

~10 s

sealedSubclasses lists the direct subtypes of a sealed class or interface as KClass objects. For a non-sealed class it is empty. It only returns the immediate children, not grandchildren.

open as a page

How do isMarkedNullable and the arguments list work on a KType, and how do you inspect a nested generic type?

level: middleimportance: should knowfreq 38%

basics

~20 s

isMarkedNullable is true when the type was written with a question mark, like String?. The arguments list holds the type arguments; each one has a .type you can read, and you can recurse into it for nested generics.

open as a page

You have a Kotlin function with default parameter values. How do you invoke it reflectively while honoring those defaults, and why can't java.lang.reflect do this?

level: middleimportance: should knowfreq 40%

basics

~10 s

Use kotlin-reflect's callBy with a map of only the parameters you want to set; the others use their defaults. Java reflection cannot do this because Java has no idea Kotlin defaults exist.

open as a page

Why does iterating Kotlin properties via KProperty give a cleaner result than iterating java.lang.reflect Fields, and how do the two views relate?

level: middleimportance: should knowfreq 38%

basics

~10 s

A Kotlin property is one logical unit, but in bytecode it becomes a field plus getter/setter methods. KProperty shows it as one property; Java reflection shows the separate pieces and may show synthetic ones.

open as a page

How does Kotlin resolve which function an overloaded callable reference like ::println points to, and how do you disambiguate?

level: seniorimportance: should knowfreq 30%

basics

~20 s

When a name is overloaded, the compiler picks the overload by looking at the expected function type from the context. If that isn't enough, you add an explicit type to tell it which one you mean.

open as a page

A callable reference is both a function value and a reflection handle. What reflective information can you read off it, and what runtime dependency does that require?

level: seniorimportance: should knowfreq 45%

basics

~10 s

A reference object also exposes metadata like its name and parameters because it's a KCallable. Reading that metadata at runtime needs the kotlin-reflect library on the classpath; just calling the reference does not.

open as a page

What does setting isAccessible = true do on a KCallable, and what are the risks of reaching private members reflectively?

level: seniorimportance: should knowfreq 35%

basics

~20 s

isAccessible = true turns off the JVM access check so you can call() or get()/set() a private function, property, or constructor that you'd otherwise be blocked from. It's powerful but bypasses encapsulation and can break under the module system or a SecurityManager.

open as a page

A teammate adds kotlin-reflect manually and pins it to a version different from the Kotlin compiler. What can go wrong, and how should the kotlin-reflect version be managed in a Gradle build?

level: seniorimportance: should knowfreq 30%

basics

~10 s

kotlin-reflect must match your Kotlin compiler version. A mismatch can cause incompatible-metadata warnings or runtime failures. Let the Kotlin Gradle plugin manage the version instead of hardcoding one.

open as a page

How do you inspect a KFunction's parameters, returnType, and visibility, and what do the KParameter.kind values mean?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Read function.parameters to get a list of KParameter (each has name, type, index, and a kind), function.returnType for the result type, and function.visibility for public/internal/etc. The kind tells you if a parameter is the receiver or a normal value.

open as a page

How do `isSubclassOf()` / `isSuperclassOf()` work on KClass, and how do they differ from `isInstance()` and the `is` operator?

level: seniorimportance: should knowfreq 35%

basics

~20 s

a.isSubclassOf(b) checks whether class a is the same as or descends from class b — a class-to-class relationship. isInstance(x) and is check whether a value belongs to a type. The first compares two KClasses; the others test an object.

open as a page

What is the difference between Int::class.java and Int::class.javaObjectType, and when does it bite you?

level: seniorimportance: should knowfreq 35%

basics

~10 s

For number-like types, .java may give the primitive class (like int) while .javaObjectType gives the boxed wrapper (like Integer). Some Java APIs only accept the wrapper, so the wrong one fails.

open as a page

showing 1–30 of 40