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 pageshowhide
explore
- How Kotlin Does Reflection & Metaprogramming5 questions
- Kotlin Reflection (kotlin-reflect)40 questions
- KClass & ::class References5 questions
- KClass vs Java Class (.java/.kotlin)5 questions
- KCallable, KFunction & KProperty5 questions
- Callable References (::fn, ::prop)5 questions
- Calling Members Reflectively5 questions
- KType & typeOf()5 questions
- kotlin-reflect Dependency & Cost5 questions
- Kotlin vs Java Reflection5 questions
- Annotations30 questions
- Declaring Annotations5 questions
- Annotation Parameters5 questions
- @Retention & @Target5 questions
- Use-Site Targets (@get:/@param:/@field:)5 questions
- Meta-Annotations & @Repeatable5 questions
- Reading Annotations Reflectively5 questions
- Serialization Core (kotlinx.serialization)25 questions
- @Serializable & Plugin Codegen5 questions
- KSerializer & Generated Serializers5 questions
- @SerialName, @Transient & @Required5 questions
- SerializersModule & Polymorphism5 questions
- Contextual Serialization5 questions
- Serialization Formats37 questions
- JSON Configuration (Json {})6 questions
- JsonElement & Dynamic JSON5 questions
- Binary Formats (ProtoBuf, CBOR)5 questions
- Custom Serializers6 questions
- Sealed-Class Polymorphic Serialization5 questions
- Schema Evolution & Defaults5 questions
- Deserialization Safety5 questions
questions
137 · 5 sectionsHow Kotlin Does Reflection & Metaprogramming
all 5 How Kotlin Does Reflection & Metaprogramming questions →What is a KClass in Kotlin reflection, how do you obtain one, and how does it differ from java.lang.Class?
basics
~20 sA 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.
How do annotations and use-site targets work in Kotlin, and why are targets like @get:, @field:, @param: necessary?
basics
~20 sA 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.
Explain the KCallable hierarchy — KCallable, KFunction, KProperty — and how you call or read members reflectively.
basics
~10 sKCallable 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.
How does Kotlin represent generic types at runtime via KType, and how do typeOf<T>() and reified parameters overcome JVM type erasure?
basics
~10 sThe 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.
How does the kotlinx.serialization @Serializable plugin generate serializers at compile time, and why is that different from reflection-based serialization?
basics
~20 sThe @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.
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?
basics
~10 sA 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).
How do you invoke a function at runtime using Kotlin reflection's KFunction.call(), and what arguments must you pass?
basics
~20 sYou 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.
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?
basics
~10 sBasic things like ::class work without extra setup. Richer reflection (reading properties, functions, parameters, supertypes) needs the separate kotlin-reflect library added to your build.
How do you obtain a KClass in Kotlin, and what is the difference between writing `instance::class` and `String::class`?
basics
~20 sUse ::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.
In Kotlin, how do you convert a KClass to a java.lang.Class and back again? Name the exact extension properties.
basics
~10 sKotlin 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.
What types are allowed as parameters of a Kotlin annotation, and which types are NOT allowed?
basics
~10 sAnnotation 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.
How do you declare your own annotation in Kotlin, and how do you apply it to a function?
basics
~10 sWrite 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.
What are meta-annotations in Kotlin, and which built-in ones can you place on an annotation declaration?
basics
~10 sMeta-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.
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?
basics
~10 sUse 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.
What do the @Retention and @Target meta-annotations control when you declare your own Kotlin annotation?
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.
Serialization Core (kotlinx.serialization)
all 25 Serialization Core (kotlinx.serialization) questions →In kotlinx.serialization, what does @Contextual do and why would you need it for a type like java.util.Date?
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.
In kotlinx.serialization, what is a KSerializer<T> and what are the three things every serializer must provide?
basics
~20 sA 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.
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?
basics
~10 sPut @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.
What does the @Serializable annotation actually do at compile time, and why doesn't kotlinx.serialization need runtime reflection like many Java JSON libraries?
basics
~10 sAdding @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.
What is a SerializersModule in kotlinx.serialization, and when do you need one?
basics
~10 sA 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.
In kotlinx.serialization, what is a custom KSerializer and when would you write one by hand instead of relying on the @Serializable-generated serializer?
basics
~20 sIt 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.
How and why do you enforce domain invariants on a @Serializable class so that an invalid instance can never be deserialized?
basics
~10 sPut 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.
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?
basics
~10 sMark 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.
In kotlinx.serialization, what is JsonElement and what are its main subtypes? When would you use it instead of a typed @Serializable data class?
basics
~20 sJsonElement 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.
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?
basics
~10 sGive 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.