How to Pass a Kotlin Interview: Advanced Questions

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

How to Pass a Kotlin Interview: Top Advanced Questions

\n\n

A Kotlin developer interview is not just a syntax check. At an advanced level, interviewers want to see a deep understanding of the language, its features, and the ability to write efficient, concise, and safe code. In this article, we will cover key topics that often appear in technical interviews: coroutines, inline functions, Sealed classes, delegation, and lambda tricks. This material is prepared for the educational portal PythonLib, where we help developers systematize their knowledge.

\n\n

1. Coroutines and Structured Concurrency

\n

Coroutines are the foundation of asynchronous programming in Kotlin. Questions on this topic show whether you understand how the scheduler, context, and exception handling work.

\n\n

What is Structured Concurrency and why is it needed?

\n

Structured Concurrency is a principle where the lifecycle of a coroutine is tied to a scope. If a parent coroutine is cancelled, all child tasks are automatically cancelled. This prevents memory leaks and makes the code predictable.

\n\n
fun main() = runBlocking {\n    launch {\n        delay(1000)\n        println("Task 1 completed")\n    }\n    launch {\n        delay(500)\n        println("Task 2 completed")\n    }\n    println("Main thread is not blocked")\n}\n
\n\n

Difference between launch and async

\n

launch starts a coroutine that does not return a result (Unit). async returns a Deferred, from which you can get the result via await(). async is convenient for parallel computations.

\n\n
val deferred1 = async { calculateSum(10, 20) }\nval deferred2 = async { calculateSum(30, 40) }\nval result = deferred1.await() + deferred2.await()\nprintln("Sum: $result")\n
\n\n

Exception handling in coroutines

\n

Use try-catch inside a coroutine or CoroutineExceptionHandler for global handling. It is important to remember that exceptions in launch propagate up the hierarchy, while in async they are stored until await() is called.

\n\n
val handler = CoroutineExceptionHandler { _, exception ->\n    println("Error: ${exception.message}")\n}\n\nfun main() = runBlocking {\n    val job = launch(handler) {\n        throw RuntimeException("Something went wrong")\n    }\n}\n
\n\n

2. Inline functions, reified, and crossinline

\n

These mechanisms allow you to optimize performance and work with generics at runtime. Interviewers often ask about the difference between inline, noinline, and crossinline.

\n\n

Why are inline functions needed?

\n

Inline functions substitute the function body directly at the call site. This eliminates the overhead of creating lambda objects. It is especially useful for higher-order functions.

\n\n
inline fun measureTime(action: () -> Unit) {\n    val start = System.currentTimeMillis()\n    action()\n    println("Time: ${System.currentTimeMillis() - start} ms")\n}\n
\n\n

What is reified?

\n

With reified, you can get type information inside an inline function, which is impossible for regular generics due to type erasure.

\n\n
inline fun <reified T> isInstance(value: Any): Boolean {\n    return value is T\n}\n\nfun main() {\n    println(isInstance<String>("Hello")) // true\n}\n
\n\n

Difference between noinline and crossinline

\n
    \n
  • noinline — prevents inlining of a specific lambda (e.g., if it is passed to another function).
  • \n
  • crossinline — allows inlining but prohibits non-local return from the lambda, which is safe for asynchronous calls.
  • \n
\n

Blogs

Book Recommendations