Kotlin Interview Questions — Beginner to Pro
“Kotlin is a programming language that makes developers happier :),” Quoted by JetBrains and the open-source contributors. I have to agree with this.
A programming language is basically how we developers communicate with computers. For over a decade we have been using several programming languages which were biased towards the computer and not the developers.
My programming career started with C, then it was C++, Java, etc. I always thought what if we could talk to the computers like we talk to any other human being?
For me, Kotlin gives me the freedom to write programs like I write a movie script or narrate a story. And I have found solace in Kotlin because it is expressive, concise, and safe.
Now those few words don’t clearly explain the beauty of Kotlin. So I am going to walk you through the advantages of this language in a Q and A model.
Moreover, these are some of the questions I usually ask my fellow candidates in interviews. I will keep adding questions every week.
Kotlin Interview Questions — Beginner Level
1. What is the difference between val
and var
in Kotlin?
Answer:
In Kotlin, val
is equivalent to Java's final keyword. They are immutable, once assigned a value it cannot be changed. var
is mutable like a normal variable.
var a = 10
a = 12 // compiles
val b = 20
b = 21 // compile time error: val cannot be reassigned
2. Are the below statements syntactically correct?
var number // line 1
number = 10 //line 2
Answer:
No. This gives us a compile-time error. Kotlin uses type inference at compile-time, which infers the type of a variable either from the value assigned to it or from the annotation of the data type given. So the above line of code gives an error as the variable “number” doesn’t explicitly mention any of it and the compiler cannot make out, what type is number.
3. Give the output of the following program
fun main() {
var employee1 = Employee("maria", 1)
var employee2 = Employee("john", 2)
var employee3 = Employee("peter", 3)
var employee4 = Employee("peter", 3)
println(employee1 == employee2)
println(employee3 == employee4)
println(employee1.equals(employee2))
println(employee3.equals(employee4))
}
class Employee(var name: String, var id: Int) {
override fun equals(obj: Any?): Boolean {
if (obj is Employee) {
return name == obj.name && id == obj.id
}
return false
}
}
Answer:
false, true, false, true
== and .equals are both the same in Kotlin. Unlike in Java, they both check for structural equality.
4. How do you check referential equality in Kotlin?
Answer:
===
using this triple equals operator.
5. What is the difference between Unit and Nothing in Kotlin?
Answer:
Unit
“It is the Java counterpart of void”.
If a function does not return anything useful or it has nothing to give us back that interests us, we say it is implicitly returning Unit. And such functions may be performing something with a side effect. Either it is going to log/print something or do a manipulation without a return value.
fun printHelloUnit(name: String?): Unit {
if (name != null)
println("Hello $name")
else
println("Hi there!")
}
//The Unit return type declaration is also optional. The above code is equivalent to:
fun printHello(name: String?) {
if (name != null)
println("Hello $name")
else
println("Hi there!")
}
In the above example, when you explicitly mention the return type as Unit, the compiler suggests removing the explicit mention as the Unit type is redundant.
Nothing
Nothing literally, means “no return to life, the game ends there ;)”. That is your function is never going to return from here, it will either throw an exception or go into an infinite loop.
Also, any code that you write after a call to a function with return type Nothing
will be marked as unreachable by the compiler.
So to conclude :
Unit says, “I will return but with no value that is of your interest”. And Nothing says “I will never return ”. Thus it helps you separately mention the nature of your function with more clarity.
Here is your example code:
class NothingClass {
fun returnName(isSuccess: Boolean): String? {
return if (isSuccess) {
println("Sara")
"Sara"
} else null
}
fun reportError(): Nothing {
println("no name found")
throw RuntimeException()
// var i = 1 // unreachable code
}
// here if you don't specify Nothing explicitly, it shows compile time error
fun iWillAlwaysThrowException() : Nothing = throwException("Unnecessary Exception")
}
fun main() {
val nothingClass = NothingClass()
val name: String = nothingClass.returnName(true) ?: nothingClass.reportError() // Compiles and the return type is String or Nothing
val noName: String = nothingClass.returnName(false) ?: nothingClass.reportException()
}
6. What is the output of the following snippet?
var student = Student("Elsa", 1234)
var twinStudent = student
fun main() {
twinStudent.name = "Rachel"
println(student.name)
}
Answer:
It is Rachel.
Here both student and twinStudent point to the same object, which means they have the same reference in memory. Any change introduced internally on either of them will be reflected on the other. Note that word internally ->It means any changes on the properties of the object and not the object on a whole.
The following picture will make things clearer for you :
You can see that the property name changes internally and the change is applied to both student and twinStudent unanimously.
7. How do you create a Singleton Class in Kotlin?
Answer:
Just use the keyword “object”..that's it!
object classname {
}
Now I am quickly going to give you a gist of what that piece of code means.
Don’t take it lightly. Because Singleton class/ pattern is a very important software design pattern irrespective of the language in use.
To start with, you need to understand what it means.
A singleton class literally means “Single all the time”. It restricts itself to getting instantiated multiple times and once an instance of a singleton class is created it will remain forever as the only instance of this class across the application/app.
In Java we follow a couple of steps to create a singleton class :
- private constructor
- static getInstance() method which says:
If (no instance of class exists )-> create one ,
else -> return existing instance
3. synchronize the getInstance() method to ensure thread safety.
Now that is a lot of boilerplate. Kotlin narrows down all the above steps into a single step making the developer's job easier.
All you need to do is :
object classname {
}
Now to understand what happens at the backstage, decompile this piece of code:
Go to Tools ▸ Kotlin ▸ Show Kotlin Bytecode and click the Decompile button at the top of the Kotlin Bytecode window. And you see the following:
public final class classname {
@NotNull
public static final classname INSTANCE;
private classname() {
}
static {
classname var0 = new classname();
INSTANCE = var0;
}
}
Voila, Kotlin got you covered.
8. What is the difference between a companion object and an object?
Answer:
Kotlin has “object ” for singletons. And “companion object” is a variation of the concept of object: It is a singleton object that belongs to a particular class. That is like a companion to a class. It cannot stand independently.
Like a baby in a Kangaroo’s pouch. Being a companion to a particular class, it will have access to all its private level methods and properties through its outer class instance.
So here is an example of a cake shop. Whenever a new cake is baked, you need to increment the cakeCount and the variable cakeCount should be shared across all the instances of cake.
class Cake(var flavour: String) {
init {
println("Baked with Love : $flavour cake ")
incrementCakeCount()
}
private fun incrementCakeCount() {
cakeCount += 1
}
companion object {
var cakeCount = 0
}
}
fun main() {
val cake1 = Cake("Chocolate")
val cake2 = Cake("Vanilla")
val cake3 = Cake("Butterscotch")
println(Cake.cakeCount)
}
PS: The idea is almost close to that of a static inner class in Java. But remember classes are classes in Kotlin, which can be instantiated multiple times and the “object” keyword is for a real object with a single instance and all the members are instance members.
9. Is it possible to write a function outside a class (A package-level / Top-level function ) in Kotlin?
Answer:
Unlike in Java, we can write a function outside a class in Kotlin. If the function logic is independent of the properties or purpose of a class, it has to go out.
Well, this becomes possible as Kotlin is not exclusively an object-oriented language and it can be used in functional ways too.
And these are functions and members within a Kotlin file, and not a class.
In the previous example for the cake shop, if I need a function to convert cups to ml while measuring my ingredients, it need not be part of the class Cake. So I am going to put it in a separate file called BakingHelpers with all my helper functions for baking included in it.
package com.basic.bakinghelpers
fun convertCupsToML(cup: Int): Int {
return cup * 237
}
So to conclude with :
- It makes things simple and clean
- The callers of your function need not declare and create an object to use this function.
10. Will the following code snippet compile?
class Bird(name: String) {
fun capitalizeBirdName(){
name.replaceFirstChar { it.uppercase() }
}
}
Answer:
No. It will not compile. Here “name” is just a parameter of the constructor and not a property of the constructor. We are trying to access the parameter “name” within a function of the class and that is restricted here.
So what is the difference between a constructor property and a constructor parameter?
A parameter is just a variable that is normally part of a function’s signature. And constructor is also a type of function and can have parameters, and they are called parameterized constructors.
Here the parameter name can be accessed only within the init{} block of the constructor or along with other property declarations of the class.
To fix the code, we can perform the manipulation in the init block, or we can create a property that is equivalent to the parameter name:
class Bird(name: String) {
// usage in the init block
init {
println(name.replaceFirstChar { it.uppercase() })
}
}
or
class Bird(name: String) {
// Here we create a property name and assign parameter to the property name
var name : String = name
fun capitalizeBirdName(){
name.replaceFirstChar { it.uppercase() }
}
}
And the above code can be optimized further by converting your parameter into a property within the constructor itself. You can convert your constructor parameter into a property by just adding a val or var to the parameter.
class Bird(var name: String) {
fun capitalizeBirdName(){
name.replaceFirstChar { it.uppercase() }
}
}
Property is much more than a regular parameter.
- It can have default setters and getters.
- It can be accessed anywhere in the class
- It may have field to store data.
In the above snippet, “name” is no longer a parameter, but a property of the class, and it can be accessed anywhere in the class. And now the code compiles right.
11. Does Kotlin have primitive datatypes?
Answer:
Well, it does have, but under the hood and not meant for developers to directly use them in code.
Let us look at the first line, var i0 = 5.
It uses the reference type “Int” in Koltin and under the hood, the compiler maps the reference type into the primitive type “int”, as it is quite obvious that variable i0 is never going to be null. The same applies in the second line for variable i1 as well.
For both the variables i0 and i1, they are going to :
- Get pushed into the stack.
- Stores the value 5 directly in them, just like any other primitive type.
But for the 3rd line, variable i2 is nullable and hence the compiler retains the reference type and does not remove the primitive wrapper. It would autobox the value 4 to the “Integer” type and keep it as an object in the heap memory.
And for variable i2:
- It gets pushed to the stack.
- It would autobox the value 4 to an Integer type and create an object in heap memory.
- Instead of storing the value 4 directly into i2, it stores the reference (address) of the object i2 in the heap memory.
So to conclude, Kotlin does the job of mapping the reference type to a primitive type whenever possible under the hood without bothering the developers. From the developer's point of view, we do not handle primitive types in Kotlin and we get to touch only the reference type.
I personally consider this a very convenient feature and definitely saves us from a lot of chaos.
12. Does the following code snippet compile? (Here we are trying to assign a variable of type Int to Long)
val a: Int = 1 // A boxed Int (java.lang.Integer)
val b: Long = a
Answer:
In Java we know, it is possible to assign a smaller type to a bigger type through implicit type casting or type promotion for primitive types (or through the valueOf() method).
But in Kotlin, it is not possible and this would give a compile-time error on line 2. “Smaller types are NOT implicitly converted to bigger types in Kotlin”.
Though Int is a 32-bit integer and long is a 64-bit integer, assigning a smaller type to a bigger type is restricted as it would compromise the equality and identity of these datatypes. So to do this right you need to explicitly convert Int to Long:
val a: Int= = 1 // A boxed Int (java.lang.Integer)
val b: Long = a.toLong()
Now that code compiles right.
13. What is the difference between “is” and “as” operators in Kotlin?
Answer:
“is” is for typechecking. You are checking the type first and then doing the job.
Example: You have got some dough and you would like to use it to bake a pizza base.
if(dough is PizzaDough){
dough.bake()
}else return
That came out very clean with an added advantage of smart casting. The compiler is smart enough to smart cast your dough to PizzaDough without you having to do this : (PizzaDough) dough explicitly.
But note that smart casts work only when the compiler can guarantee that the variable won’t change between the type check and the point of usage.
“as” is for typecasting.
What if your dough was meant for making tortillas and you are casting your dough to PizzaDough under the assumption that it would work?
val pizzaDough = tortillaDough as PizzaDough
When you forcefully try to cast your TortillaDough to PizzaDough, it fails with a ClassCastException.
An exception is definitely not a developer’s forte. You really don’t want that to happen, so the fix would be -> Safe Cast(as?)
val pizzaDough:PizzaDough? = tortillaDough as? PizzaDough
This would save us from an exception as this will return null if the casting fails. And you get to bake your pizza and make your tortillas without an exception.
14. What is a class constructor?
This question is not specific to Kotlin. But you really have to get this right if you are dealing with an object-oriented programming language.
First, let’s split the question into smaller subquestions to understand it deeply.
- What is a class and an object?
I am using the analogy of the cupcake and the cupcake mould to explain the idea of a class and an object.
Envision class as your cupcake mould and object as your cupcake.
We get to eat the delicious cupcakes only when you pour the cupcake mix into the mould and bake it. A mould remains a virtual idea and it takes life or adds value only when we pour the cupcake mix into it and bake it. Similarly, an “object is what exists for real” and “class is just an idea”.
You could make different types of cupcakes of varying flavors, shapes and colors from a cupcake mould. Flavor, Shape, color: We call them the properties.
You may have to calculate the calories or the expiry date of your cupcake before you sell them. Functions like calculateExpiryDate() and calculateCaloriesPerServing() helps you do that. We call them behaviour.
To conclude class is a template with properties and behaviour. Object is created when we assign some real values to the properties and start manipulating using its functions. Any number of objects can be created from a class.
class CupCake(val flavor: String, val size: String) {
fun calculateCaloriesPerServing(){
//TODO
}
fun calculateExpiryDate(){
//TODO
}
}
2. What is a primary and secondary constructor?
Now that we have the cupcake mould ready. We need to construct/create our cupcakes. Now that’s the job of a constructor. They help us construct the object in different ways. Constructor is nothing but a method that performs the job of object instantiation.
The basic version is called the primary constructor. In Kotlin, it is part of your class header.
class CupCake(val shape: String, val size: String)
It could be a parameterless constructor (default constructor)as well.
class CupCake
You can write the code logic for your primary constructor only in an “init” block and it is executed immediately after object instantiation.
class CupCake(val shape: String, val size: String) {
init {
println("Primary Constructor")
}
}
And if you wish to go further and provide some more options to construct your object. Eg: If you want to give the user an option to choose an eggless version or a sugar-free version of your cupcake, you can easily add one or more parameters “isEggless”, “isSugarFree” to the existing constructor.
But If you keep doing this to the primary constructor. It would encumber your constructor and disrupt the concise nature of Kotlin.
What if somebody wants a basic version of the cupcake? You have to unnecessarily carry those extra parameters in your code and do the basic checks every time. That would make your code cumbersome. So better keep it separate.
Create a secondary constructor with the new parameter list and delegate the old parameters to your primary constructor.
PS: In Kotlin the secondary constructor always has to delegate to the primary constructor, if your primary constructor has parameters.
class CupCake(val shape: String, val size: String) {
constructor(shape: String, size: String, isEggless: Boolean) : this(shape, size){
//TODO
}
}
That’s it! Now you have a primary constructor which would give you a basic vanilla cupcake and a secondary constructor which helps you make an eggless version of it.
3. Heading to the final part of this question. How to bake it?
How to create an instance of a class or object?
“It is just a method call”
Step 1: Get your cupcake mix ready by assigning the desired values:
flavour = "vanilla"
size = "small"
Step 2: Pour the mix into the Cupcake mould and bake it.
You need to call your constructor to perform this action.
Here you go:
var vanillaCupCake = CupCake("vanilla", "medium")
or
var eggLessVanillaCupCake = CupCake("vanilla", "medium",true)
It returns an instance of your medium-sized eggless vanilla cupcake which you refer to as the object. Bon appétit!
to be continued….