skip to content

Reflection, Annotations & Serialization

Runtime introspection with kotlin-reflect, declaring and reading annotations, and kotlinx.serialization's compile-time codegen. The theme interviewers pull on is Kotlin's preference for generating code at compile time over reflecting at runtime.

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

explore

questions

137 · 5 sections

What is a KClass in Kotlin reflection, how do you obtain one, and how does it differ from java.lang.Class?

level: juniorimportance: must knowfreq 55%
basics
~20 s

A KClass is Kotlin's runtime handle to a class. You get it with String::class for a type or instance::class for an object. It exposes Kotlin features like properties and nullability; java.lang.Class only knows the Java view.

open as a page

How do annotations and use-site targets work in Kotlin, and why are targets like @get:, @field:, @param: necessary?

level: middleimportance: must knowfreq 50%
basics
~20 s

A single Kotlin property compiles into several JVM elements: a field, a getter, a constructor parameter. Use-site targets like @field: or @get: tell the compiler which one the annotation lands on, since each may need it.

open as a page

Explain the KCallable hierarchy — KCallable, KFunction, KProperty — and how you call or read members reflectively.

level: middleimportance: should knowfreq 45%
basics
~10 s

KCallable is the common type for anything you can call: functions and properties. KFunction is invoked with call(args). KProperty has a getter you read with get(receiver); mutable ones (KMutableProperty) also have a setter.

open as a page

How does Kotlin represent generic types at runtime via KType, and how do typeOf<T>() and reified parameters overcome JVM type erasure?

level: seniorimportance: should knowfreq 30%
basics
~10 s

The JVM erases generics, so List<String> looks like List at runtime. Kotlin's typeOf<T>() captures the full type, and reified type parameters in inline functions keep T available so you can inspect or use it.

open as a page

How does the kotlinx.serialization @Serializable plugin generate serializers at compile time, and why is that different from reflection-based serialization?

level: seniorimportance: should knowfreq 40%
basics
~20 s

The @Serializable compiler plugin writes a serializer for your class while it compiles, so no runtime reflection is needed. Reflection-based tools instead inspect the class at runtime, which is slower and harder to use on native or minified targets.

open as a page

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

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 types are allowed as parameters of a Kotlin annotation, and which types are NOT allowed?

level: juniorimportance: must knowfreq 60%
basics
~10 s

Annotation parameters can only be simple compile-time values: numbers, Boolean, Char, String, enums, a class reference, another annotation, and arrays of those. You cannot use arbitrary objects like a List or a date.

open as a page

How do you declare your own annotation in Kotlin, and how do you apply it to a function?

level: juniorimportance: must knowfreq 60%
basics
~10 s

Write a class with the annotation class keywords, for example annotation class Loggable. Then put @Loggable in front of a function, property, or class to mark it.

open as a page

What are meta-annotations in Kotlin, and which built-in ones can you place on an annotation declaration?

level: juniorimportance: must knowfreq 55%
basics
~10 s

Meta-annotations are annotations you put on another annotation's declaration to describe how it behaves. The built-in ones are @Retention, @Target, @MustBeDocumented, and @Repeatable.

open as a page

In Kotlin, how do you read an annotation off a class at runtime, and what must be true of that annotation for it to be visible?

level: juniorimportance: must knowfreq 55%
basics
~10 s

Use Kotlin reflection: get the class with ::class, look at its annotations list, or call findAnnotation. The annotation only shows up at runtime if it was declared with RUNTIME retention.

open as a page

What do the @Retention and @Target meta-annotations control when you declare your own Kotlin annotation?

level: juniorimportance: must knowfreq 55%
basics
~10 s

@Retention says how long the annotation is kept: source only, in the class file, or readable at runtime. @Target says where you can put it: on classes, functions, properties, parameters, and so on.

open as a page

In kotlinx.serialization, what does @Contextual do and why would you need it for a type like java.util.Date?

level: juniorimportance: must knowfreq 55%
basics
~10 s

@Contextual tells the serializer: don't pick a serializer at compile time for this property. Look one up at runtime from a registered module. You use it for types you can't annotate, like java.util.Date.

open as a page

In kotlinx.serialization, what is a KSerializer<T> and what are the three things every serializer must provide?

level: juniorimportance: must knowfreq 65%
basics
~20 s

A KSerializer<T> is the object that knows how to turn a value of type T into a stream of data and read it back. It provides a serialize function, a deserialize function, and a descriptor describing the type.

open as a page

How do you make a kotlinx.serialization property serialize under a different JSON key than its Kotlin name, and what is the role of @SerialName?

level: juniorimportance: must knowfreq 75%
basics
~10 s

Put @SerialName("json_key") on the property. The Kotlin field keeps its name in code, but the JSON uses the name you give. Useful when JSON uses snake_case but Kotlin uses camelCase.

open as a page

What does the @Serializable annotation actually do at compile time, and why doesn't kotlinx.serialization need runtime reflection like many Java JSON libraries?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Adding @Serializable tells a compiler plugin to generate the code that reads and writes the class. Because that code is built when you compile, the library doesn't have to inspect the class at runtime.

open as a page

What is a SerializersModule in kotlinx.serialization, and when do you need one?

level: juniorimportance: must knowfreq 55%
basics
~10 s

A SerializersModule is a registry that tells the serialization library how to handle types it cannot figure out on its own, like interfaces or open base classes with many possible subtypes.

open as a page

In kotlinx.serialization, what is a custom KSerializer and when would you write one by hand instead of relying on the @Serializable-generated serializer?

level: juniorimportance: must knowfreq 60%
basics
~20 s

It is a small class that tells the library exactly how to turn one type into data and back. You write one when the default behavior is wrong, for types you cannot annotate, or when the wire format must differ from your class.

open as a page

How and why do you enforce domain invariants on a @Serializable class so that an invalid instance can never be deserialized?

level: juniorimportance: must knowfreq 55%
basics
~10 s

Put checks in the class's init {} block using require(). Deserialization calls the real constructor, so the checks run too. Bad input throws instead of producing a broken object.

open as a page

How do you turn a Kotlin object into a JSON string and back using kotlinx.serialization, and what is the role of the Json object?

level: juniorimportance: must knowfreq 80%
basics
~10 s

Mark the class with @Serializable, then call Json.encodeToString(obj) to get JSON text and Json.decodeFromString(text) to read it back. Json is the format instance that does the conversion.

open as a page

In kotlinx.serialization, what is JsonElement and what are its main subtypes? When would you use it instead of a typed @Serializable data class?

level: juniorimportance: must knowfreq 70%
basics
~20 s

JsonElement is a flexible in-memory tree for JSON when you don't have a fixed class. Its parts are JsonObject (key-value), JsonArray (list), and JsonPrimitive (string, number, boolean, or null). Use it when the JSON shape is unknown or changes.

open as a page

You add a new property to a kotlinx.serialization @Serializable class, but old JSON payloads don't contain it. How do you make deserialization of those old payloads still succeed?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Give the new property a default value. When the field is missing from the JSON, kotlinx.serialization uses the default, so old messages still load without errors.

open as a page