Interview Preparation

Kotlin Interview Questions

Master the most commonly asked interview questions with comprehensive, expert-crafted answers designed to help you succeed.

16
Questions
100%
Expert Answers
Q1
Explain about the “when” keyword in the context of Kotlin.

The when keyword in Kotlin is a powerful control flow expression that acts as a substitute for the switch statement found in languages like Java. It allows you to execute a block of code based on the value of a variable or expression. Each branch is checked sequentially until a match is found, and once a matching case is executed, the control flow exits the when block. Unlike Java's switch, Kotlin's when does not require a break statement at the end of each branch.

Example:

fun main(args: Array<String>) {
    val temp = "Interview"
    when(temp) {
        "Interview" -> println("Interview Bit is the solution.")
        "Job" -> println("Interview is the solution.")
        "Success" -> println("Hard Work is the solution.")
    }
}

Output:

Interview Bit is the solution.

Explanation: The variable temp holds the value "Interview". The when block compares this value against each branch, and upon finding a match, executes the corresponding statement. Since there's no need for a break, the flow automatically exits after execution.

Q2
What are the advantages of Kotlin over Java?

Kotlin offers several advantages over Java that make it a preferred choice for modern Android and backend development:

  • Data Classes: Kotlin reduces boilerplate code with data classes. In Java, you have to manually write getters, setters, equals(), hashCode(), and toString() methods, whereas Kotlin automatically generates them.
  • Concise Getters and Setters: In Kotlin, you don’t need to explicitly write getters and setters. If needed, Kotlin allows you to define custom getters and setters in a much more concise way than Java. It also supports property delegation for reusable patterns.
  • Extension Functions: Kotlin allows developers to extend the functionality of existing classes with extension functions without having to inherit from them. Java lacks built-in support for this feature.
  • Multi-platform Support: Kotlin supports multi-platform development, allowing developers to share code across Android, iOS, and web apps from a single codebase using Kotlin Multiplatform.
  • Null Safety: Kotlin has built-in null safety through nullable and non-nullable types, which helps eliminate the common NullPointerException errors found in Java code.
  • Error Reduction: Kotlin’s concise and expressive syntax reduces the likelihood of errors and makes the code more readable and maintainable compared to Java.
Q3
What are the basic data types in Kotlin?

In Kotlin, the basic data types include:

  • Numbers: Byte, Short, Int, Long, Float, Double
  • Characters: Char
  • Booleans: Boolean
  • Strings: String
  • Arrays: Array<T>, IntArray, FloatArray, etc.

Here is an example demonstrating usage of these types:

val age: Int = 25
val price: Double = 19.99
val grade: Char = 'A'
val isActive: Boolean = true
val name: String = "Kotlin"
val numbers: Array<Int> = arrayOf(1, 2, 3, 4)
Q4
Differentiate between open and public keywords in Kotlin.

In Kotlin, the open and public keywords serve different purposes, particularly in terms of inheritance and visibility.

  • open: By default, classes and methods in Kotlin are final, meaning they cannot be inherited or overridden. The open keyword allows a class or method to be extended or overridden. For example, marking a class or method as open means it is 'open for extension', similar to not marking a class as final in Java.
  • public: This keyword defines visibility. In Kotlin, if no visibility modifier is explicitly declared, public is used by default. This means the declaration is accessible from any other code in the same module or project. It doesn’t affect inheritance or overriding, only how accessible the element is.

In summary, open allows inheritance and overriding, while public controls visibility. You need both if you want to allow external code to access and override a method.

Q5
What is Extension Function?

In Kotlin, an Extension Function allows developers to extend the functionality of an existing class without inheriting from it or using design patterns such as Decorator. This means you can add new methods to classes even if you don't have access to their source code.

To declare an extension function, you use the syntax where the function name is prefixed with the class you want to extend, followed by a dot:

fun <ClassName>.<MethodName>() { 
    // method body 
}

For example, you can define a new function for the String class like this:

fun String.printUpperCase() {
    println(this.uppercase())
}

After this, any String object can call printUpperCase() as if it were a built-in method. Extension functions do not actually modify the classes they extend; instead, they are resolved statically at compile time.

Q6
How many Constructors are there in Kotlin?

In Kotlin, there are two types of constructors used to create and initialize objects of a class: Primary Constructor and Secondary Constructor.

1. Primary Constructor:

The primary constructor is part of the class header and provides a concise way to initialize class properties. It does not contain any logic by itself and is typically used for straightforward initialization.

class Student(val firstName: String, var age: Int) {
    // class body
}

2. Secondary Constructor:

Secondary constructors are declared inside the class body using the constructor keyword. These constructors allow you to provide additional initialization logic or different ways to instantiate a class.

class MyCourse {
    constructor(id: Int) {
        // initialization logic
    }

    constructor(name: String, id: Int) {
        // initialization logic
    }
}

While the primary constructor is often sufficient for most needs, secondary constructors are useful when you need multiple ways to instantiate a class with different parameters.

Q7
Do primary and secondary constructors have any relationship?

Yes, in Kotlin, there is a relationship between primary and secondary constructors. When a secondary constructor is defined, it must explicitly delegate to the primary constructor, either directly or indirectly. This ensures that the primary constructor's initialization logic is always executed when an object is created.

This is done using the this keyword within the secondary constructor to call the primary constructor.

class Person(val name: String) {
    constructor(name: String, age: Int) : this(name) {
        // additional initialization
    }
}

In this example, the secondary constructor delegates to the primary constructor using : this(name), ensuring that the name property is initialized correctly.

Q8
What is the critical difference between ‘var’ and ‘val’ for Variable declaration in Kotlin?

In Kotlin, the keywords var and val are used to declare variables, and they differ primarily in terms of mutability.

  • var (mutable): Used when the variable's value can change during the program's execution. Variables declared with var are mutable.
  • val (immutable): Used when the variable's value is read-only and cannot be changed once it is assigned. It behaves like a final variable in Java.
var age = 25
age = 30 // allowed

val name = "Kotlin"
name = "Java" // Error: Val cannot be reassigned

This distinction enforces safer coding practices by encouraging immutability wherever possible, reducing bugs due to unintended value changes.

Q9
Is Kotlin functional or OOP?

Kotlin is a modern, versatile programming language that supports both object-oriented programming (OOP) and functional programming paradigms. It allows developers to write clean, maintainable code by combining the best of both worlds.

As an object-oriented language, Kotlin supports classes, objects, inheritance, encapsulation, and polymorphism. You can define data models, encapsulate behavior, and structure applications using traditional OOP techniques.

At the same time, Kotlin also supports functional programming features such as higher-order functions, lambda expressions, map/filter/reduce operations, and immutable data. These features promote a more declarative and concise coding style that is ideal for handling collections and side-effect-free logic.

This dual capability makes Kotlin highly expressive and suitable for a wide range of programming needs, whether you prefer functional constructs or object-oriented design.

Q10
In Kotlin, what is the difference between lateinit and lazy?

In Kotlin, both lateinit and lazy are used for delayed initialization, but they differ significantly in usage and behavior. Below is a comparison:

lateinitlazy
Can only be used with var.Can only be used with val.
Can be initialized multiple times.Initialized only once and then cached.
Can be initialized from any part of the class.Must be initialized using the initializer lambda.
Cannot be used with primitive types.Can be used with primitive types.
Q11
What is the main difference between FlatMap and Map?

In Kotlin, both map and flatMap are functional programming constructs used for transforming collections, but they behave differently in terms of output structure.

map is used to transform each element of a collection individually using a transformation function. It returns a list where each item is the result of the transformation function applied to the corresponding element in the original list.

flatMap is used when each transformation produces a collection itself (e.g., a list of items for each element). It flattens the resulting nested lists into a single list.

Example:

// Using map
val mapped = listOf(1, 2, 3).map { listOf(it, -it) }
println(mapped) // Output: [[1, -1], [2, -2], [3, -3]]

// Using flatMap
val flatMapped = listOf(1, 2, 3).flatMap { listOf(it, -it) }
println(flatMapped) // Output: [1, -1, 2, -2, 3, -3]
Q12
What is Kotlin Null Safety?

Null Safety in Kotlin is a feature designed to eliminate the risk of null references in your code, commonly known as the 'billion-dollar mistake'. Kotlin enforces strict null checks during compilation, helping developers avoid NullPointerException at runtime.

In Kotlin, variables are non-nullable by default. If you want a variable to hold a null value, you must explicitly declare it as nullable by appending a ? to its type. The compiler will then require you to handle the possibility of null values using safe call operators (?.), the Elvis operator (?:), or other null-handling constructs.

Example:

var name: String = "Kotlin"
name = null // Compilation error

var nullableName: String? = "Kotlin"
nullableName = null // This is allowed

By enforcing null safety at compile time, Kotlin significantly reduces the chances of runtime null-related crashes, leading to more stable and reliable code.

Q13
How do you handle nullability in Kotlin?

In Kotlin, nullability is handled through built-in language features that ensure safe access and manipulation of nullable types. Kotlin distinguishes between nullable and non-nullable variables at the type level, helping developers avoid NullPointerException errors.

1. Safe Calls (?.):

The safe call operator is used to safely access a property or call a method on a nullable object. If the object is null, the entire expression evaluates to null instead of throwing an exception.

val length: Int? = text?.length

2. Elvis Operator (?:):

The Elvis operator provides a default value if the expression on the left is null. This helps ensure a non-null result.

val length: Int = text?.length ?: 0

3. Safe Casts (as?):

The safe cast operator attempts to cast a value to a specific type. If the cast is not possible, it returns null instead of throwing an exception.

val name: String? = value as? String

4. Non-Null Assertion Operator (!!):

If you're certain that a nullable variable is not null, you can use the non-null assertion operator to force the compiler to treat it as non-null. If the value is actually null, a NullPointerException will be thrown.

val length: Int = text!!.length

By using these features, Kotlin ensures a safer and more predictable handling of null values, reducing the likelihood of runtime exceptions.

Q14
What is the Elvis operator in Kotlin?

The Elvis operator in Kotlin, represented by ?:, is a concise and elegant way to assign a default value when dealing with nullable expressions. It is particularly useful in scenarios where a variable might be null, and you want to provide an alternative value to avoid NullPointerException.

Syntax:

val result = nullableObject ?: defaultValue

If nullableObject is not null, the expression evaluates to nullableObject. Otherwise, it evaluates to defaultValue.

Example:

val name: String? = null
val length: Int = name?.length ?: 0

In this example, the variable name is nullable. The safe call operator ?. attempts to get the length of name. If name is null, the Elvis operator ensures that 0 is assigned to the length variable as a default value.

The Elvis operator simplifies null checks and enhances code readability by reducing the need for verbose if-else conditions.

Q15
What are coroutines in Kotlin?

Coroutines in Kotlin are a concurrency design pattern that allows for efficient and structured asynchronous programming. They provide a way to write asynchronous code that looks like sequential code, making it easier to understand and maintain.

Coroutines can suspend execution without blocking the thread, allowing for non-blocking I/O operations and concurrent computations. They are designed to handle asynchronous tasks in a structured and sequential manner.

import kotlinx.coroutines.*

fun main() = runBlocking {
    val job = launch {
        delay(1000L)
        println("Coroutine executed")
    }

    println("Hello")
    job.join()
    println("World")
}

In the example, we use the launch function from the kotlinx.coroutines package to create a coroutine. Inside the coroutine, we use the delay function to suspend execution for 1000 milliseconds (1 second). The output is printed before and after the coroutine execution. The runBlocking function is used to start the coroutine and block the main thread until it completes.

Coroutines simplify asynchronous programming by providing a structured and intuitive way to handle concurrency and parallelism.

Q16
What's the difference between blocking and suspending?

Blocking a call to a function means that any further calls from the same thread will cause the parent’s execution to halt. If a blocking call is made on the main thread, the UI freezes and the user sees a static screen until the call is completed. This is undesirable in UI-driven applications.

Suspending, on the other hand, does not necessarily stop the parent function from executing. Suspended functions can be moved to a different thread, allowing the main thread to remain responsive. When a suspension point is reached, the execution pauses and the thread is freed for other work, resuming only when necessary. This enables efficient and non-blocking asynchronous programming.

Why Choose Our Question Bank?

Get access to expertly crafted answers and comprehensive preparation materials

Complete Collection

Access all 16 carefully curated questions covering every aspect of Kotlin interviews

Expert Answers

Get detailed, professional answers crafted by industry experts with real-world experience

Instant Access

Start preparing immediately with instant access to all questions and answers after sign-up