50 Kotlin Interview Q & A

Bubu Tripathy
17 min readMay 3, 2023

What is Kotlin, and what is it used for?

Kotlin is a statically-typed programming language that runs on the Java Virtual Machine (JVM). It’s used for developing Android apps, web applications, desktop applications, and server-side applications.

What are the advantages of using Kotlin?

Kotlin has many advantages, such as concise syntax, null safety, interoperability with Java, higher-order functions, and extension functions.

What are the basic data types in Kotlin?

The basic data types in Kotlin are Int, Long, Float, Double, Char, Boolean, and String.

val x: Int = 1
val y: Long = 2L
val z: Float = 3.14f
val w: Double = 3.14159
val c: Char = 'a'
val b: Boolean = true
val s: String = "Hello, World!"

How do you declare a variable in Kotlin?

In Kotlin, you can declare a variable using the “var” or “val” keyword. “var” is used for mutable variables, while “val” is used for immutable variables.

var x: Int = 1 // mutable variable
val y: Int = 2 // immutable variable

What is null safety in Kotlin?

Null safety is a feature in Kotlin that helps prevent null pointer exceptions. In Kotlin, all variables must be initialized, and the compiler checks that a variable is not null before allowing it to be used.

var s: String? = null // nullable variable
s?.length // safe call operator to access length only if s is not null

What is the Elvis operator in Kotlin?

The Elvis operator (?:) is a shorthand for checking if a variable is null and providing a default value if it is.

val s: String? = null
val length = s?.length ?: 0 // if s is null, length will be 0

What are extension functions in Kotlin?

Extension functions allow you to add functionality to an existing class without modifying the class itself. They are defined outside the class and can be used as if they were part of the class.

fun String.reverse(): String {
return this.reversed()
}

val s = "hello"
val reversed = s.reverse() // "olleh"

What are higher-order functions in Kotlin?

Higher-order functions are functions that take other functions as parameters or return functions as results. They are a powerful feature of Kotlin that allows you to write more concise and expressive code.

fun performOperation(x: Int, operation: (Int) -> Int): Int {
return operation(x)
}

val result = performOperation(5) { x -> x * x } // 25

What is a lambda expression in Kotlin?

A lambda expression is a way to define a function in a concise and readable way. It’s defined using curly braces and can be passed as a parameter to a higher-order function.

val square = { x: Int -> x * x }

val result = square(5) // 25

What is a higher-order function type in Kotlin?

A higher-order function type is a type that represents a function that takes other functions as parameters or returns functions as results. The syntax for a higher-order function type is (parameterType) -> returnType.

val operation: (Int, (Int) -> Int) -> Int = { x, f -> f(x) }

val result = operation(5) { x -> x * x } // 25

What is a companion object in Kotlin?

A companion object is an object that belongs to a class and can be accessed using the class name. It’s similar to a static method in Java.

class MyClass {
companion object {
fun create(): MyClass {
return MyClass()
}
}
}

val myClass = MyClass.create()

What is the difference between “object” and “class” in Kotlin?

A class is a blueprint for creating objects, while an object is a single instance of a class that is created at runtime. An object cannot be instantiated using a constructor, while a class can be.

class MyClass

object MyObject

val myClass = MyClass()
val myObject = MyObject

What is a sealed class in Kotlin?

A sealed class is a class that can only be extended within the same file. It’s often used to define a restricted hierarchy of classes.

sealed class Shape

class Circle(val radius: Double): Shape()

class Rectangle(val width: Double, val height: Double): Shape()

fun printArea(shape: Shape) {
when (shape) {
is Circle -> println("Area of circle: ${Math.PI * shape.radius * shape.radius}")
is Rectangle -> println("Area of rectangle: ${shape.width * shape.height}")
}
}

val circle = Circle(5.0)
val rectangle = Rectangle(5.0, 10.0)

printArea(circle) // "Area of circle: 78.53981633974483"
printArea(rectangle) // "Area of rectangle: 50.0"

What is the difference between a property and a field in Kotlin?

A property is a member variable of a class that can have a getter and/or a setter. A field is the storage location for a property, which can be either a backing field (for properties with a custom getter/setter) or a regular field (for properties with a simple getter/setter).

class Person {
var name: String = ""
get() = field.toUpperCase()
set(value) {
field = value.trim()
}
}

In this example, the “name” property is declared with a backing field and a getter/setter method. The getter method returns the value of the backing field in uppercase letters, while the setter method trims the whitespace from the input value before setting it to the backing field.

When you access the “name” property in code, you’re actually calling the getter/setter methods, not the backing field directly.

val person = Person()
person.name = " Alice "
println(person.name) // prints "ALICE"

In this example, the “name” property is set to “ Alice “ using the setter method, which trims the whitespace before setting the value to the backing field. The getter method then returns the value of the backing field in uppercase letters, which is printed to the console.

What is a data class in Kotlin?

A data class is a class that is designed to hold data. It automatically generates methods such as toString(), equals(), hashCode(), and copy() based on the class properties.

data class Person(val name: String, val age: Int)

val person1 = Person("Alice", 30)
val person2 = Person("Bob", 40)

println(person1) // "Person(name=Alice, age=30)"
println(person1 == person2) // false
val person3 = person1.copy(name = "Charlie")
println(person3) // "Person(name=Charlie, age=30)"

What is a delegate in Kotlin?

In Kotlin, a delegate is a design pattern that allows objects to delegate certain responsibilities to other objects, without having to implement those responsibilities themselves. It is a way to achieve composition over inheritance, and it promotes code reuse and modularity.

In Kotlin, delegation is implemented using the by keyword. To use a delegate, you define a property in a class and specify the delegate using the by keyword, followed by an instance of the delegate class. The delegate class must implement certain methods or provide certain functionality that the delegated property requires.

interface Base {
fun print()
}

class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}

class Derived(b: Base) : Base by b

fun main() {
val b = BaseImpl(10)
Derived(b).print()
}

The class BaseImpl implements the Base interface and has a property x of type Int. The print() function of the Base interface is overridden in this class to print the value of x.

The class Derived also implements the Base interface but uses the by keyword to delegate the implementation of Base to the constructor parameter b. This means that all calls to print() on Derived will be forwarded to b.

In the main() function, an instance of BaseImpl is created with a value of 10. Then, a Derived instance is created, passing in the BaseImpl instance as the constructor argument. Finally, print() is called on the Derived instance, which delegates the call to BaseImpl, resulting in the value 10 being printed to the console.

Explain the “when” expression in Kotlin.

The “when” expression is a replacement for the traditional “switch” statement in other languages. It allows you to check a value against multiple cases and execute different code blocks based on the value.

fun printMessage(x: Int) {
when (x) {
1 -> println("One")
2 -> println("Two")
in 3..5 -> println("Three to Five")
else -> println("Other")
}
}

printMessage(2) // "Two"
printMessage(4) // "Three to Five"
printMessage(6) // "Other"

What is a lazy property in Kotlin?

A lazy property is a property that is only initialized when it’s first accessed. It’s useful for properties that are expensive to compute or require external resources.

val myLazyProperty: String by lazy {
println("Initializing...")
"Hello, World!"
}

println(myLazyProperty) // "Initializing..." and "Hello, World!"
println(myLazyProperty) // "Hello, World!" (already initialized)

What is the difference between a range and an iterable in Kotlin?

A range is a sequence of values that can be expressed using the “..” or “until” operators, while an iterable is a collection of values that can be iterated over using a for loop or other iteration methods.

val range = 1..5 // range from 1 to 5 (inclusive)
val iterable = listOf(1, 2, 3, 4, 5) // list of values

for (i in range) {
println(i) // 1, 2, 3, 4, 5
}

for (i in iterable) {
println(i) // 1, 2, 3, 4, 5
}

What is the difference between a mutable and an immutable collection in Kotlin?

A mutable collection can be modified after it’s created, while an immutable collection cannot. In Kotlin, mutable collections have a “Mutable” prefix, such as MutableList or MutableSet, while immutable collections have no prefix, such as List or Set.

val mutableList = mutableListOf(1, 2, 3)
mutableList.add(4)
println(mutableList) // [1, 2, 3, 4]

val immutableList = listOf(1, 2, 3)
// immutableList.add(4) // compile error
println(immutableList) // [1, 2, 3]

What is a coroutine in Kotlin?

A coroutine is a lightweight thread that can be suspended and resumed later. It allows you to write asynchronous code in a sequential and readable way.

fun main() {
println("Start")
GlobalScope.launch {
delay(1000)
println("Coroutine")
}
println("End")
Thread.sleep(2000)
}

// Output: Start, End, Coroutine (after 1 second)

What is a suspend function in Kotlin?

A suspend function is a function that can be paused and resumed later from within a coroutine. It’s marked with the “suspend” keyword.

suspend fun fetchData(): List<String> {
delay(1000)
return listOf("Data 1", "Data 2", "Data 3")
}

fun main() {
println("Start")
GlobalScope.launch {
val data = fetchData()
println(data)
}
println("End")
Thread.sleep(2000)
}

// Output: Start, End, [Data 1, Data 2, Data 3] (after 1 second)

What is the “let” function in Kotlin?

“let” is a function that allows you to execute a block of code on a non-null object. It’s similar to the “if (obj != null)” check in Java.

val str: String? = "Hello"
str?.let {
println(it.toUpperCase()) // "HELLO"
}

What is the “apply” function in Kotlin?

“apply” is a function that allows you to initialize an object and perform multiple operations on it in a fluent way.

class Person {
var name: String = ""
var age: Int = 0
}

val person = Person().apply {
name = "Alice"
age = 30
}
println(person.name) // "Alice"
println(person.age) // 30

What is the “also” function in Kotlin?

“also” is a function that allows you to perform an additional operation on an object and return the same object. It’s similar to the “tap” function in JavaScript.

class Person(var name: String, var age: Int)

val person = Person("Alice", 30).also {
it.name = "Bob"
it.age += 1
}
println(person.name) // prints "Alice"
println(person.age) // prints "31"

In this example, the “also” function is used to perform a series of operations on the “person” object and return the original object itself.

What is the “takeIf” function in Kotlin?

“takeIf” is a function that allows you to check a condition on an object and return the object if the condition is true or null otherwise.

val str: String? = "Hello"
val result = str?.takeIf { it.length > 5 }
println(result) // "Hello"

What is the “takeUnless” function in Kotlin?

“takeUnless” is a function that allows you to check a condition on an object and return the object if the condition is false or null otherwise.

val str: String? = "Hello"
val result = str?.takeUnless { it.length <= 5 }
println(result) // "Hello"

What is the “require” function in Kotlin?

“require” is a function that allows you to check a condition on a parameter and throw an IllegalArgumentException if the condition is false.

fun divide(a: Int, b: Int) {
require(b != 0) { "Divisor must not be zero" }
println(a / b)
}

divide(10, 2) // 5
divide(10, 0) // IllegalArgumentException: Divisor must not be zero

What is the “check” function in Kotlin?

“check” is a function that allows you to check a condition on a parameter and throw an IllegalStateException if the condition is false.

fun checkState(state: Boolean) {
check(state) { "Invalid state" }
}

checkState(true) // no exception
checkState(false) // IllegalStateException: Invalid state

What is the “run” function in Kotlin?

“run” is a function that allows you to execute a block of code on an object and return the result of the block.

val str = "Hello"
val result = str.run {
println(toUpperCase()) // "HELLO"
length
}
println(result) // 5

What is the “repeat” function in Kotlin?

“repeat” is a function that allows you to execute a block of code multiple times.

repeat(3) {
println("Hello")
}

// Output: "Hello", "Hello", "Hello"

What is the “buildString” function in Kotlin?

“buildString” is a function that allows you to build a string using a block of code.

val str = buildString {
append("Hello, ")
append("World!")
}
println(str) // "Hello, World!"

What is the “use” function in Kotlin?

“use” is a function that allows you to execute a block of code on a resource and automatically close the resource after the block is executed.

File("file.txt").bufferedReader().use { reader ->
reader.lines().forEach {
println(it)
}
}

What is the “with” function in Kotlin?

The “with” keyword in Kotlin is a way to execute a series of operations on an object without having to repeatedly reference the object. It’s a way to simplify code and make it more readable. Here is an example:

class Person(var name: String, var age: Int)

val person = Person("Alice", 30)
with(person) {
name = "Bob"
age += 1
}
println(person.name) // prints "Bob"
println(person.age) // prints "31"

What is the difference between “let” and “apply” in Kotlin?

Both “let” and “apply” are functions that allow you to perform operations on an object, but they differ in their return value and usage. “let” returns a value that is derived from the input object, while “apply” returns the original input object. “let” is often used for null-safe operations, while “apply” is often used for initializing objects in a fluent way.

What is the difference between “run” and “apply” in Kotlin?

Both “run” and “apply” are functions that allow you to perform operations on an object, but they differ in their return value and usage. “run” returns the result of the block of code, while “apply” returns the original input object. “run” is often used for performing calculations or transformations, while “apply” is often used for initializing objects in a fluent way.

What is the difference between “lateinit” and “nullable” properties in Kotlin?

“lateinit” is a modifier that allows you to declare a non-null property that is initialized later, while “nullable” is a modifier that allows you to declare a property that can be null. “lateinit” should only be used for non-primitive types that are guaranteed to be initialized before they are used, while “nullable” should be used for types that may or may not have a value.

What is the “by lazy” delegate in Kotlin?

The “by lazy” delegate is a way to lazily initialize a property. It allows you to initialize a property the first time it is accessed, rather than when it is declared. This can be useful for expensive or time-consuming initialization, or for properties that may not be used in all scenarios.

What is the “it” keyword in Kotlin?

The “it” keyword in Kotlin is a shorthand way to refer to the single parameter of a lambda expression. It’s often used to simplify code when the lambda expression has only one parameter. Here is an example:

val list = listOf("apple", "banana", "cherry")
val result = list.filter { it.startsWith("a") }
println(result) // prints "[apple]"

What is the difference between “sealed class” and “enum class” in Kotlin?

Both “sealed class” and “enum class” are used to define a fixed set of values or states, but they differ in their flexibility and extensibility. “enum class” is a more rigid construct that defines a fixed set of values that cannot be extended or modified, while “sealed class” is a more flexible construct that allows for a fixed set of values that can be extended and modified. Here is an example of using an “enum class”:

enum class Color {
RED, GREEN, BLUE
}
val color = Color.RED

In this example, the “Color” enum class is defined with three values: RED, GREEN, and BLUE. The “color” variable is assigned the value RED, which is one of the defined values of the enum class. Here is an example of using a “sealed class”:

sealed class Result {
data class Success(val value: Int) : Result()
data class Error(val message: String) : Result()
}
val result: Result = Result.Success(42)

In this example, the “Result” sealed class is defined with two subclasses: “Success” and “Error”. The “result” variable is assigned an instance of the “Success” subclass with a value of 42. The sealed class allows for the fixed set of values to be extended and modified by defining new subclasses.

What is the difference between a “primary constructor” and a “secondary constructor” in Kotlin?

A primary constructor in Kotlin is the main constructor that is defined in a class declaration. It’s responsible for initializing the properties of the class and can also include parameter validation or other initialization logic.

A secondary constructor in Kotlin is an additional constructor that is defined in a class declaration. It provides an alternative way to create instances of the class and can include different parameter types or a different initialization logic. Here is an example of using a primary constructor:

class Person(val name: String, val age: Int) {
init {
require(age >= 0) { "Age cannot be negative" }
}
}
val person = Person("Alice", 30)

In this example, the “Person” class has a primary constructor that takes two parameters: “name” and “age”. The constructor also includes an initialization block that checks if the age is not negative. An instance of the “Person” class is created with the “name” and “age” parameters. Here is an example of using a secondary constructor:

class Person(val name: String, val age: Int) {
constructor(name: String) : this(name, 0)
}
val person = Person("Alice")

In this example, the “Person” class has a primary constructor that takes two parameters: “name” and “age”. The class also has a secondary constructor that takes only the “name” parameter and sets the “age” parameter to 0. An instance of the “Person” class is created using the secondary constructor with only the “name” parameter.

What is the difference between “filter” and “map” in Kotlin?

Both “filter” and “map” are higher-order functions that operate on collections in Kotlin, but they differ in their usage and output. “filter” is used to select a subset of elements from a collection based on a predicate, while “map” is used to transform each element of a collection based on a function. Here is an example of using “filter”:

val numbers = listOf(1, 2, 3, 4, 5)
val evenNumbers = numbers.filter { it % 2 == 0 }
println(evenNumbers) // prints "[2, 4]"

Here is an example of using “map”:

val numbers = listOf(1, 2, 3, 4, 5)
val squaredNumbers = numbers.map { it * it }
println(squaredNumbers) // prints "[1, 4, 9, 16, 25]"

What is the difference between “forEach” and “forEachIndexed” in Kotlin?

Both “forEach” and “forEachIndexed” are higher-order functions that operate on collections in Kotlin, but they differ in their output and usage. “forEach” is used to perform an operation on each element of a collection, while “forEachIndexed” is used to perform an operation on each element of a collection along with its index. Here is an example of using “forEach”:

val numbers = listOf(1, 2, 3)
numbers.forEach { println(it) }
// prints:
// 1
// 2
// 3

Here is an example of using “forEachIndexed”:

val numbers = listOf(1, 2, 3)
numbers.forEachIndexed { index, value -> println("$index: $value") }
// prints:
// 0: 1
// 1: 2
// 2: 3

What are properties in Kotlin, and how are they used?

Properties in Kotlin are variables that are associated with a class. Properties can be declared using the val or var keywords, which determine whether the property is read-only or mutable. Properties can have a backing field that stores the value of the property, or they can be computed properties that are calculated on-the-fly.

class Person(val name: String, var age: Int)

val john = Person("John", 30)
john.age = 31

println("${john.name} is ${john.age} years old.") // John is 31 years old.

In this example, name is a read-only property that is initialized in the constructor and cannot be modified. age is a mutable property that can be modified after the object is created. The val and var keywords are used to declare the properties.

What is a generic class in Kotlin, and how is it used?

A generic class in Kotlin is a class that can work with different types of data. Generic classes are defined using angle brackets <> and a type parameter that represents the type of data that the class will work with. Generic classes are used to create reusable code that can be used with multiple types of data.

class Box<T>(var contents: T)

val boxOfInts = Box<Int>(42)
val boxOfString = Box<String>("Hello, world!")

println("Box of ints contains: ${boxOfInts.contents}")
println("Box of string contains: ${boxOfString.contents}")

How does overriding work in Kotlin, and how is it used?

Overriding in Kotlin is the mechanism by which a subclass can provide its own implementation of a function that is already defined in the parent class. To override a function in Kotlin, the override keyword is used before the function declaration in the subclass.

open class Animal(val name: String) {
open fun makeSound() {
println("$name is making a sound.")
}
}

class Cat(name: String) : Animal(name) {
override fun makeSound() {
println("$name is meowing.")
}
}

class Dog(name: String) : Animal(name) {
override fun makeSound() {
println("$name is barking.")
}
}

fun makeAnimalSound(animal: Animal) {
animal.makeSound()
}

val animal = Animal("Generic Animal")
val cat = Cat("Whiskers")
val dog = Dog("Fido")

makeAnimalSound(animal) // Generic Animal is making a sound.
makeAnimalSound(cat) // Whiskers is meowing.
makeAnimalSound(dog) // Fido is barking.

What is a lambda with receiver in Kotlin, and how is it used?

A lambda with receiver in Kotlin is a lambda expression that is used to extend the functionality of an object. A lambda with receiver is defined using the . operator before the lambda declaration.

fun buildString(builderAction: StringBuilder.() -> Unit): String {
val stringBuilder = StringBuilder()
stringBuilder.builderAction()
return stringBuilder.toString()
}

val message = buildString {
append("Hello, ")
append("World!")
}

println(message) // Hello, World!

In this example, buildString is a function that takes a lambda with receiver StringBuilder.() -> Unit as a parameter. The lambda expression can access the properties and functions of the StringBuilder class using the this keyword. The buildString function creates a new StringBuilder object and calls the lambda with receiver on it. The resulting string is returned.

What is a type alias in Kotlin, and how is it used?

A type alias in Kotlin is a way to provide a new name for an existing type. Type aliases are defined using the typealias keyword and can be used to simplify complex types or provide more descriptive names for existing types.

typealias EmployeeId = String

data class Employee(val id: EmployeeId, val name: String)

val employee = Employee("1234", "John Doe")

println("Employee ${employee.name} has ID ${employee.id}.") // Employee John Doe has ID 1234.

In this example, EmployeeId is a type alias for the String type. The Employee class uses the EmployeeId type alias to define its id property.

How does the lateinit keyword work in Kotlin, and how is it used?

The lateinit keyword in Kotlin is used to declare a variable that will be initialized later, before it is used. The lateinit keyword can only be used with mutable variables that are declared with the var keyword.

class Person {
lateinit var name: String

fun initializeName() {
name = "John Doe"
}

fun printName() {
println("Name: $name")
}
}

val person = Person()

person.initializeName()
person.printName()

What is a reified type parameter in Kotlin, and how is it used?

A reified type parameter in Kotlin is a type parameter that can be accessed at runtime. Reified type parameters are declared using the reified keyword before the type parameter name.

inline fun <reified T> List<T>.printElementType() {
println(T::class.simpleName)
}

val list = listOf("one", "two", "three")
list.printElementType<String>()

In this example, an extension function printElementType() is defined for the List<T> class with a reified type parameter T. The function is used to print the type of the elements in the list using the ::class syntax. The extension function is called on a List<String> object and the type parameter is specified as String. The output of the function is String, which is the type of the elements in the list. By using the reified type parameter, the type can be accessed at runtime without using reflection.

Thank you for your attention! Happy Learning!

--

--