Authors Top

If you have a few years of experience with the Kotlin language and server-side development, and you’re interested in sharing that experience with the community, have a look at our Contribution Guidelines.

1. Overview

In this tutorial, we’ll discuss a few usual interview questions for Kotlin.

We categorize the questions into beginner and advanced levels for ease of understanding.

2. Beginner Level Questions

2.1. What Is Kotlin? How Is It Interoperable With Java?

Kotlin is a general-purpose JVM-based programming language designed and developed by JetBrains. It’s a statically-typed programming language that supports procedural, functional, and object-oriented programming.

The Kotlin compiler generates the bytecode that is 100% equivalent to the bytecode generated by the Java compiler. Hence, it can seamlessly interoperate with Java.

A few handy features like range expressions, extension functions, null-safety, and smart casts make Kotlin a better alternative over Java.

Additionally, Google promotes Kotlin as the official language for Android development.

2.2. What Are the Different Types of Variable Declaration in Kotlin?

In Kotlin, we can either use the val or var keyword followed by an optional data type to declare a variable:

val userName: String = "John"
var age = 25

The val keyword creates a final immutable variable that allows initialization only once. However, var creates a mutable general-purpose variable suitable for multiple assignments.

When we declare a variable without a data type, Kotlin uses the smart cast feature to determine the data type based on the value assignment.

Also, we can use the const keyword along with val to declare compile-time constants.

2.3. What’s the Difference Between val and const?

The val keyword creates an immutable variable at runtime, whereas const along with val allows creating a compile-time immutable variable (constant):

val welcomeMsg: String = "Hello $userName"
const val FILE_EXTENSION: String = ".jpg"

Also, we can declare global or local immutable variables using the val keyword, assignable to a function or any class constructor.

However, we can’t assign it to a function or any class constructor as Kotlin decides the value of the const variable at compile-time.

2.4. How to Create Constructors in Kotlin?

There are two types of constructors available in Kotlin – primary and secondary. A Kotlin class can have one primary constructor and one or more secondary constructors.

In Kotlin, we initialize the primary constructor in the class header with a var or val variable declaration:

class Person (var firstName: String, var lastName: String) {
    var age: Int = 0
}

var person = Person("John", "Smith");

However, a secondary constructor definition can’t have variable declaration with the var and val keywords:

class Person (var firstName: String, var lastName: String) {
    var age: Int = 0

    constructor (firstName: String, age: Int) {
        this.firstName = firstName
        this.age = age
    }
}

 var personWithAge = Person("John", 27);

Also, a secondary constructor can use the primary constructor internally in the definition:

constructor (firstName: String, lastName: String, age: Int): this(firstName, lastName) {
    this.age = age
}

2.5. Describe String Interpolation in Kotlin

Kotlin supports two ways of String interpolation – variable substitution using $ and interpolating an expression using ${}. For example:

var welcomeMsg = "Hello $userName";
var secondsInOneYear = "${60 * 60 * 24 * 365} seconds"

2.6. What’s Null-Safety in Kotlin?

Null safety in Kotlin guarantees that no object references shall have null or void values.

By default, Kotlin doesn’t allow a variable to have a null value. So, it eliminates the risk of encountering the notorious NullPointerException in the production environment.

However, if required, we can define a variable with the null reference by using ? after the data type:

var name : String?

2.7. What Are the Data Classes in Kotlin?

Kotlin encourages code brevity by reducing boilerplate code. For example, the data class provides a way to write concise and readable POJOs.

They eliminate the need to define getters/setters, parameterized constructors, and override methods like hashcode and equals.

All of this is possible in Kotlin by simply adding the data keyword to the class:

data class Person(var firstName: String, var lastName: String)

Furthermore, apart from usual POJO methods like equals, hashCode, and toString, it also creates a few built-in functions like open and componentN.

2.8. How to Create a Singleton Class in Kotlin?

Similar to the data class, Kotlin reduces boilerplate code in defining a singleton class by using the object keyword:

object SimpleSingleton

The Kotlin compiler internally implements a singleton class with a thread-safe lazy initialization.

2.9. What Is a Double-Bang Operator in Kotlin?

Kotlin’s double bang (!!) operator is a not-null assertion operator. It converts any variable to a non-null type and throws the NullPointerException if it’s null.

So, a developer should use this operator when they are certain for a variable to be not null in any case.

2.10. What Are the Range Expressions in Kotlin?

A range is a sequence of values defined by start and end values. Range expressions in Kotlin help to iterate over a range.

Kotlin provides the rangeTo and downTo functions to create a range. Alternatively, we can also use the double dots (..) operator to define a range of values.

For example, let’s define a few ranges in Kotlin:

(i in 1..10) // range from 1 to 10

(i in 1.rangeTo(10)) // range from 1 to 10

(i in 10.downTo(1)) // range from 10 down to 1

(ch in 'a'..'z') // range from a to z

(i in 1..10 step 2) // range from 1 to 10 with a step of 2 (1, 3, 5, 7, 9)

Also, Kotlin allows a few handy functions like reverse, until, first, and last over range expressions for various use cases.

2.11. Explain when in Kotlin

Kotlin’s when is an advanced version of Java’s switch-case statements.

When a matching expression is found, Kotlin executes the corresponding code and moves to the next statement:

when (person.firstName) {
    "Mike" -> println("hello!")
    "John" -> println("howdy!")
    else -> println("hi!")
}

Unlike Java, Kotlin doesn’t require a break statement at the end of each case block. Furthermore, Kotlin’s when is useful both as a statement and as an expression.

2.12. List All Access Modifiers Available in Kotlin. Which Access Modifier Is Used by Default?

There are four access modifiers available in Kotlinpublic, private, protected, and internal.

Similar to Java, the public modifier in Kotlin provides global visibility to the declarations. It’s the default modifier in Kotlin when not declared.

Similarly, the private modifier is the opposite of the public modifier. Hence, it allows accessing the declarations within the file.

However, the protected declarations are secured and not available to the top-level declarations.

Unlike Java, Kotlin has an internal modifier that provides access to the declarations anywhere in the module.

2.13. Define open in Kotlin

Unlike Java, which allows extending classes and methods by default, Kotlin uses the open keyword to enable others to inherit them. In other words, it’s opposite to Java’s final keyword.

Kotlin keeps everything final, and through the open keyword, it supports the philosophy of limiting the extension of the classes unless required.

3. Advanced Level Questions

3.1. What Are the Advantages of Kotlin Over Java?

Kotlin, a JVM programming language, provides tools to write concise, easy, and readable code that’s interoperable with Java.

Furthermore, it’s an official programming language for Andriod development that supports major programming paradigms, like OOP, procedural, and functional.

Also, Kotlin fills a few gaps that Java possesses – null safety, range expressions, string templates, coroutines, inline – infix functions, and smart casts.

3.2. Define inline and infix Functions

Kotlin’s inline functions allow the compiler to substitute the body directly into places (inlines) where the function gets called:

inline fun isEven (number: Int): Boolean {
     return number % 2 == 0
}

val resultList = (1..10).filter { isEven(it) }

The Kotlin compiler will substitute the body of isEven directly in the filter. Hence, it prevents the object allocations for the functions or lambda expressions. For example:

So, we can write elegant lambdas with the inline keyword without worrying about abstraction and efficiency.

However, infix functions in Kotlin are some functions that can be called without using the period and brackets:

var personDetailsMap = mapOf(
    "firtName" to "john",
    "lastName" to "smith",
    "age" to 25
  )

Here, the to method is used as an infix function and results in code that’s more like a natural language – easy to read and understand.

Kotlin provides a variety of infix functions like and, or, and matches. Also, we can define custom infix functions whenever required.

3.3. Define lazy and lateinit

lazy means lazy initialization, and lateinit means late initialization.

Kotlin doesn’t initialize a lazy variable before its use. Therefore, it’s supported only by val. A lazy variable supports only a single initialization.

On the other hand, Kotlin delays initialization for a lateinit variable but expects the variable to be initialized before its use. Also, Kotlin throws the UninitializedPropertyAccessException exception without initialization.

It’s supported by var and allows multiple initializations. However, we can’t use lateinit for the primitive types.

A lazy variable can only be initialized from the initializer lambda. However, the lateinit variable allows initialization from anywhere the variable is accessible.

3.4. Define fold and reduce Functions

The fold and reduce functions traverse a collection and apply a given operation with and without initial value, respectively.

Let’s take a look at a simple operation using the fold and reduce functions:

var sum = (1..10).fold(10) { res, next -> res + next }
assertEquals(65, sum)

The first iteration of the collection with the fold function uses 10 (initial value) to start with. So, the values of res and next are 10 and 1, respectively.

sum = (1..10).reduce { res, next -> res + next }
assertEquals(55, sum)

However, the iteration starts with 1 and 2 with the reduce function.

Also, the fold function allows changing the result type by defining the data type of the initial value.

3.5. What Are the Coroutines in Kotlin?

Coroutines offer lightweight multi-threading programming in Kotlin. Also, we can leverage the suspension and resumption of coroutines mid-execution to write asynchronous programs.

The Kotlin language comes with a rich library called kotlinx-coroutines with a few modules like core, test, debug, and reactive to support multiple features.

3.6. What Are the Companion Objects in Kotlin?

Unlike Java, Kotlin doesn’t have static members or member functions. So, we can define a companion object inside the class to execute a method without the class instance.

We can declare a companion object by using the companion keyword:

class Person(var firstName: String, var lastName: String) {

    companion object {
        val defaultPerson = Person("Mike", "Shaw")
    }

    // ...
}

assertEquals("Mike", Person.defaultPerson.firstName)

However, companion objects in Kotlin are similar to the standard object with a couple of additional features to ease the development. For example, the name of a companion object is optional, and it offers singleton implementation.

3.7. Explain Bitwise Operations in Kotlin

Similar to Java, Kotlin, too, has bitwise operations like or, and, xor, and left and right shifts. However, the operators are named more intuitively than in Java.

For example, the name of Kotlin bit operators are or, and, xor, and inv:

assert(111 or 101 == 111) 
assert(111 and 101 == 101)
assert(111 xor 101 == 10)
assert(101.inv() == -102)

Similarly, the binary shift operators are shl – signed left shift, shr – signed right shift, and ushr – unsigned right shift:

assert(3 shl 3 == 24)
assert(12 shr 2 == 3)
assert(-1 ushr 1 == Int.MAX_VALUE)

4. Conclusion

In this article, we went through a few typical interview questions categorized into beginner and advanced levels.

These questions and their brief answers can give a good start to someone preparing for the Kotlin interview. However, it’s also advised to go through detailed concepts and practice enough to have good hands-on experience.

Authors Bottom

If you have a few years of experience with the Kotlin language and server-side development, and you’re interested in sharing that experience with the community, have a look at our Contribution Guidelines.

Comments are closed on this article!