Kotlin interview questions and answers

Here are 100 Kotlin interview questions and answers, covering fundamentals, object-oriented programming, functional features, coroutines, and advanced concepts, designed to prepare you for a wide range of interview scenarios.

Kotlin Fundamentals

1. What is Kotlin?
Kotlin is a modern, statically typed programming language that runs on the Java Virtual Machine (JVM) and can also be compiled to JavaScript, Android, and native code. It’s concise, safe, and fully interoperable with Java.

2. What are the key advantages of Kotlin over Java?
Null safety built into the type system, much more concise syntax (less boilerplate), data classes, extension functions, coroutines for concurrency, and first-class support for immutability.

3. How do you declare a variable in Kotlin?
Using val for read-only (immutable) references and var for mutable references. Type inference often allows omitting the explicit type: val name = "Kotlin".

4. What is the difference between val and const?
val is a runtime constant — the variable is read-only after initialization. const is a compile-time constant, only applicable for top-level or object/companion object properties of primitive or String type.

5. How does Kotlin handle null safety?
Types are non-null by default. To allow nulls, you append ? (e.g., String?). You must safely handle nullable values with safe calls (?.), the Elvis operator (?:), or explicit null checks.

6. What is the Elvis operator?
?: — if the left-hand side is not null, return it; otherwise, return the right-hand side. Example: val name = nullableName ?: "Unknown".

7. What are smart casts?
When the compiler can guarantee a type after a type check (is or !is), it automatically casts the variable to that type without an explicit cast. Works with immutable references (val).

8. Explain when expression.
A replacement for Java’s switch, but more powerful. It can match values, ranges, types, and arbitrary conditions. It returns a value if used as an expression.

9. What are ranges in Kotlin?
Expressions like 1..10 (inclusive) or 1 until 10 (exclusive) that can be used in loops and when checks. They also support in and !in operators.

10. How does string interpolation work?
You can embed variables and expressions in strings using $variableName or ${expression}. No need for concatenation.

Functions & Lambdas

11. How do you declare a function in Kotlin?
Using fun keyword, followed by name, parameters, return type, and body. Example: fun sum(a: Int, b: Int): Int = a + b.

12. What is a single-expression function?
When a function body consists of a single expression, you can omit braces and use = to return the expression’s result directly.

13. What are default arguments?
You can specify default values for function parameters. Callers can omit arguments, and the defaults will be used.

14. What are named arguments?
When calling a function, you can specify parameter names to improve readability or to skip some default parameters: formatString(str = "Hello", uppercase = true).

15. What are vararg parameters?
A parameter declared with vararg accepts a variable number of arguments of the same type, accessible as an array inside the function.

16. What are lambda expressions?
Anonymous functions that can be treated as values: passed as arguments, returned, stored in variables. Syntax: { parameters -> body }.

17. What is it in lambdas?
An implicit name for a single parameter in a lambda. If a lambda has exactly one parameter, you can omit the explicit parameter declaration and just use it.

18. What are higher-order functions?
Functions that take other functions as parameters or return a function. They enable functional programming patterns like callbacks and decorators.

19. What are extension functions?
A way to add new functionality to existing classes without inheriting from them or modifying the original class. Defined with fun Type.newFunction(...).

20. What are infix functions?
Member or extension functions with a single parameter that can be called without dot and parentheses. Declared with infix keyword. Example: 1 to "one".

Object-Oriented Programming

21. How do you define a class in Kotlin?
Using class ClassName { ... }. The primary constructor is part of the class header: class Person(val name: String). Secondary constructors use constructor.

22. What is a data class?
A class annotated with data whose primary purpose is to hold data. The compiler automatically generates equals()hashCode()toString()copy(), and component functions.

23. What are companion objects?
An object declared inside a class with the companion keyword. Its members can be accessed similarly to static members in Java, but it’s actually a singleton object.

24. How do you implement a singleton in Kotlin?
Using an object declaration. object MySingleton { ... } creates a thread-safe singleton lazily when first accessed.

25. What is the difference between object and class?
object defines a class and creates its only instance immediately (singleton). class is a blueprint from which multiple instances can be created.

26. How do you inherit a class in Kotlin?
Kotlin classes are final by default. To allow inheritance, mark the parent class with open. The child class uses : to inherit: class Child : Parent().

27. What are sealed classes?
A class hierarchy restricted to a fixed set of subclasses, all defined in the same file. It allows exhaustive when expressions without an else branch, great for modeling restricted states.

28. What are interface vs abstract class differences in Kotlin?
Interfaces can have default implementations but cannot store state (no backing fields). Abstract classes can have state (properties with backing fields) and constructors. Kotlin uses interface and abstract class.

29. How do visibility modifiers work in Kotlin?
public (default), private (within the file/class), protected (class and subclasses), internal (within the module). protected doesn’t apply to top-level declarations.

30. What are init blocks?
Code blocks inside a class body prefixed with init that run during object initialization, after the primary constructor. You can have multiple init blocks executed in order.

31. Can you explain property delegation?
Using by keyword to delegate the getter/setter logic of a property to another object. Common delegates: lazy (lazy initialization), observable (callbacks on change).

32. What is the lazy delegate?
A property delegate that computes the value on first access and caches it. The value is only computed once; thread-safety mode can be specified.

33. What are type aliases?
typealias provides an alternative name for an existing type. Useful for shortening long generic types: typealias StringList = List<String>.

34. What are inner classes vs nested classes?
Nested classes in Kotlin don’t hold a reference to the outer class by default (static-like). To hold a reference, mark it as inner.

35. How does this work in inner/nested classes?
Inside an inner class, this refers to the inner class instance. To refer to the outer class, use this@OuterClassName. Nested classes have no outer reference.

36. What are value classes (inline classes)?
Classes declared with @JvmInline value class wrapping a single value, avoiding allocation at runtime in many cases, while providing type safety.

37. What are generics in Kotlin?
Similar to Java generics with additional features: declaration-site variance (out/in), use-site variance (projections), and reified type parameters.

38. What is out and in in generics?
out marks a type parameter as covariant (producer, read-only). in marks as contravariant (consumer, write-only). They define how subtyping relationships are preserved.

39. What is a reified type parameter?
Declared with reified in an inline function, making the type accessible at runtime (normally erased). Enables operations like is T or T::class.

40. What is the Any type?
The root of the Kotlin class hierarchy, similar to Java’s Object, but not nullable; Any? is the supertype of all nullable types.

Standard Library & Idioms

41. What are scope functions?
Functions (letrunwithapplyalso) that execute a block of code on an object and provide a temporary scope. They differ in the object reference (this vs it) and the return value.

42. Explain let vs apply vs also vs run.

  • let: context object as it, returns lambda result. Good for null safety.
  • apply: context object as this, returns the same object. Used for object configuration.
  • also: like let but returns the object. Good for side effects.
  • run: context object as this, returns lambda result. Combination of with and let.

43. What are collections in Kotlin?
Standard collection interfaces: ListSetMap. There are also mutable variants like MutableList. By default, listOf() etc. return read-only interfaces.

44. What is the difference between listOf and mutableListOf?
listOf returns an immutable list (read-only), mutableListOf returns a MutableList that supports adding/removing elements.

45. What are sequence operations?
Sequences (Sequence<T>) are lazily evaluated, unlike lists whose operations are eager. They avoid intermediate collection creation and can be infinite.

46. What are filtermapreduce, and flatMap?

  • filter: returns elements matching a predicate.
  • map: transforms each element.
  • reduce: accumulates elements starting with first element.
  • flatMap: transforms each element to a collection, then flattens into a single list.

47. What are takeIf and takeUnless?
takeIf(predicate) returns the object if the predicate is true, otherwise nulltakeUnless does the opposite: returns object if predicate is false, else null.

48. What are destructuring declarations?
Extracting multiple values from an object at once: val (name, age) = person. Works on data classes (component functions) and Map.Entry.

49. What are Pair and Triple?
Standard data classes for holding two or three values. Often used to return multiple values from functions.

50. What is require and check?
require throws IllegalArgumentException if its condition fails. check throws IllegalStateException. Used for validating arguments and state.

Coroutines & Concurrency

51. What are coroutines in Kotlin?
A concurrency design pattern for writing asynchronous, non-blocking code in a sequential manner. They are lightweight threads that can be suspended without blocking the underlying thread.

52. What is the difference between coroutines and threads?
Coroutines run on a thread but can suspend, freeing the thread for other work. They are much cheaper (millions of coroutines vs. thousands of threads). They simplify asynchronous programming.

53. What does suspend mean?
A modifier for a function that can be paused and resumed later. It can call other suspend functions and use delay etc., without blocking the thread.

54. What are coroutine builders?
Functions to launch coroutines: launch (fire-and-forget, returns Job), async (returns a result via Deferred), and runBlocking (blocks the current thread, used mainly for tests/main).

55. What is Job in coroutines?
A handle to a launched coroutine used for cancellation (cancel()), joining (join()), and checking lifecycle.

56. What is Deferred?
A future-like object returned by async that holds a result. Use await() to suspend until the result is ready. It extends Job.

57. Explain structured concurrency.
Coroutines are started in a scope (CoroutineScope), and a parent coroutine waits for all its children to complete. If a child fails, the parent is cancelled, preventing leaks.

58. What are CoroutineScope and GlobalScope?
CoroutineScope defines a lifecycle for coroutines; when the scope is cancelled, all its coroutines are cancelled. GlobalScope lives as long as the application and is generally discouraged except for specific long-running tasks.

59. What is coroutineContext?
A set of elements (like JobCoroutineDispatcher, exception handler) that define the behavior of a coroutine.

60. What are dispatchers?
They determine which thread or thread pool the coroutine runs on: Dispatchers.Main (UI), Dispatchers.IO (blocking I/O), Dispatchers.Default (CPU-intensive work), Dispatchers.Unconfined.

61. How do you change the dispatcher within a coroutine?
Using withContext(dispatcher) { ... }. This suspends, switches context, executes the block, and returns to the original context after completion.

62. What is delay?
A suspending function that pauses the coroutine without blocking the thread; other coroutines can run on the same thread.

63. How do you handle exceptions in coroutines?
Coroutine builders treat exceptions differently: launch propagates to the parent/coroutine context exception handler. async defers exception until await() is called. Use supervisorScope to prevent cancellation of siblings on failure.

64. What is a Channel?
A communication primitive for sending and receiving streams of values between coroutines. Similar to blocking queues but with suspending semantics.

65. What are Flow in Kotlin?
A cold asynchronous stream that sequentially emits values and can complete or fail. It’s built on coroutines and supports operators like mapfiltercollect. Useful for reactive streams.

66. Difference between Flow and List?
Flow is lazy and can emit asynchronously over time; List is eager and all elements are immediately available. Flow doesn’t compute until collected.

67. What are StateFlow and SharedFlow?
StateFlow is a hot flow that holds a single current value and emits updates. SharedFlow is a hot flow that emits to multiple collectors and can replay a specified number of values.

68. How do you cancel a coroutine?
Call job.cancel() or scope.cancel(). The coroutine must be cooperative (checking isActive or calling suspend functions that check for cancellation). CancellationException is thrown inside the coroutine.

69. What is SupervisorJob?
Job that, when used in a scope, prevents a child’s failure from cancelling the parent or other siblings. Useful for handling partial failures.

70. What are coroutine exception handlers?
CoroutineExceptionHandler is a context element that catches uncaught exceptions in coroutines (only for launch).

Functional & Advanced Kotlin

71. What is tail recursion optimization?
Kotlin supports tailrec modifier on recursive functions. The compiler converts the recursion to a loop if the function meets the tail-recursive requirements, preventing stack overflow.

72. What is operator overloading?
You can overload predefined operators (like +-[]) for custom types by implementing specific member or extension functions with operator modifier.

73. What is an anonymous function?
A function without a name, defined with fun(parameters): ReturnType { body }. It can be used similarly to lambdas but can have an explicit return type and uses return to return from the anonymous function itself.

74. How is Kotlin interoperable with Java?
You can call Java code from Kotlin and vice versa without wrappers. Kotlin maps Java types, handles getter/setter conventions, and uses Java annotations for nullability.

75. What are the limitations when calling Kotlin from Java?
Java doesn’t understand default parameters, so Kotlin generates @JvmOverloads for overloading. Companion object members look like static but require Companion access, use @JvmStatic for direct access. Inline classes are boxed when used from Java.

76. How do you use annotations in Kotlin?
Similar to Java: @AnnotationName. You can use annotations on classes, functions, properties, etc. Some require explicit use-site targets like @get:Annotation for property getter.

77. What are inline functions?
Functions marked with inline cause the compiler to replace the function call with its body during compilation. This reduces overhead of higher-order functions (no lambda class creation). Also enables reified type parameters.

78. What is noinline and crossinline?
noinline prevents a lambda parameter of an inline function from being inlined. crossinline enforces that the lambda cannot use non-local returns (i.e., it behaves like a regular function).

79. What is Nothing type?
A type that has no instances; used to denote a function that never returns (e.g., throws an exception or infinite loop). It’s a subtype of all types.

80. What is Unit type and how does it differ from Void?
Unit is a type with a single value Unit, used as the return type of functions that don’t return a meaningful value (similar to Java’s void). It’s a real type, so it can be used as a generic argument. Void is a Java keyword with no instances.

Testing & Tooling

81. What testing frameworks are popular for Kotlin?
JUnit (4/5), Kotest (a Kotlin-native testing framework), MockK (mocking library designed for Kotlin), and Strikt for assertions.

82. How do you use MockK for mocking?
mockk<MyClass>() creates a mock, every { mocked.method() } returns valueverify { mocked.method() } to check invocations. Supports coroutines and relaxed mocks.

83. How can you test coroutines?
Using runTest (from kotlinx.coroutines.test), which provides a virtual time and skips delays, making tests fast and deterministic.

84. What is Ktor?
A Kotlin framework for building asynchronous servers and clients. It’s lightweight, fully based on coroutines, and can be used for web applications, APIs, and microservices.

85. How do you declare an Android Activity in Kotlin?
Same as Java but with Kotlin syntax: class MainActivity : AppCompatActivity() { ... }. Use Kotlin Android Extensions or View Binding for views.

86. What is KTX in Android?
A set of Kotlin extensions bundled with Android Jetpack to provide idiomatic Kotlin APIs for platform components.

87. How do you perform JSON parsing in Kotlin?
Using kotlinx.serialization (compiler plugin, type-safe), Gson, Moshi, or Jackson. Kotlin serialization is now popular because it’s multiplatform and native.

88. What is build.gradle.kts?
Gradle build script written in Kotlin instead of Groovy. Provides better IDE support with auto-completion and type safety.

Code Examples & Problem Solving

89. Write a function to reverse a string in Kotlin.
fun reverse(s: String): String = s.reversed()

90. How would you check if a number is prime?

kotlin

fun isPrime(n: Int): Boolean {
    if (n < 2) return false
    return (2..sqrt(n.toDouble()).toInt()).none { n % it == 0 }
}

91. Create a data class and use copy().

kotlin

data class User(val name: String, val age: Int)
val user1 = User("Alice", 30)
val user2 = user1.copy(age = 31)

92. Use when to return whether a character is a vowel.

kotlin

fun isVowel(c: Char) = when(c.toLowerCase()) {
    'a', 'e', 'i', 'o', 'u' -> true
    else -> false
}

93. Write a lambda that squares a number.
val square: (Int) -> Int = { it * it }

94. Example of an extension function.

kotlin

fun String.removeSpaces() = this.replace(" ", "")
val result = "Hello World".removeSpaces() // "HelloWorld"

95. How to create a lazy property?

kotlin

val heavyData: String by lazy {
    println("Computed!")
    "Result"
}

96. Demonstrate let and apply.

kotlin

val nonNull = maybeNull?.let { performOperation(it) }
val configured = MyObject().apply {
    property1 = value1
    property2 = value2
}

97. How to launch a coroutine and handle delay?

kotlin

GlobalScope.launch {
    delay(1000L)
    println("Delayed")
}

98. Use Flow to emit numbers.

kotlin

flow {
    for (i in 1..3) {
        emit(i)
        delay(100)
    }
}.collect { println(it) }

99. Explain sealed class with a real-world example.

kotlin

sealed class Result
data class Success(val data: String) : Result()
data class Error(val message: String) : Result()
// Now exhaustive when:
when(result) {
    is Success -> println(result.data)
    is Error -> println(result.message)
}

100. Where do you see Kotlin evolving?
Kotlin is increasingly multi-platform (Kotlin Multiplatform for shared business logic across iOS/Android/Web), composable UI with Jetpack Compose, and stronger server-side presence with Ktor and Spring support. Its concise, safe, and expressive nature makes it the de facto choice for modern JVM-based development.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top