Kotlin Android Interview Questions
1. How does Kotlin work on Android?
Just like Java, the Kotlin code is also compiled into the Java bytecode and is executed at runtime by the Java Virtual Machine i.e. JVM. When a Kotlin file named Main.kt
is compiled then it will eventually turn into a class and then the bytecode of the class will be generated. The name of the bytecode file will be MainKt.class
and this file will be executed by the JVM.
2. Why should we use Kotlin?
- Kotlin is concise
- Kotlin is null-safe
- Kotlin is interoperable
3. What is the difference between the variable declaration with var and val?
If you want to declare some mutable(changeable) variable, then you can use var
. For the immutable variable, use val
i.e. val
variables can't be changed once assigned.
4. What is the difference between the variable declaration with val and const?
Both the variables that are declared with val
and const
are immutable in nature. But the value of the const
variable must be known at the compile-time whereas the value of the val
variable can be assigned at runtime also.
5. How to ensure null safety in Kotlin?
One of the major advantages of using Kotlin is null safety. In Java, if you access some null variable then you will get a NullPointerException
. So, the following code in Kotlin will produce a compile-time error:
var name: String = "MindOrks"
name = null //error
So, to assign null values to a variable, you need to declare the name
variable as a nullable string and then during the access of this variable, you need to use a safe call operator i.e. ?.
var name: String? = "MindOrks"
print(name?.length) // ok
name = null // ok
6. What is the difference between safe calls(?.) and null check(!!)?
Safe call operator i.e. ?.
is used to check if the value of the variable is null or not. If it is null then null will be returned otherwise it will return the desired value.
var name: String? = "MindOrks"
println(name?.length) // 8
name = null
println(name?.length) // null
If you want to throw NullPointerException when the value of the variable is null, then you can use the null check or !!
operator.
var name: String? = "MindOrks"
println(name?.length) // 8
name = null
println(name!!.length) // KotlinNullPointerException
7. Do we have a ternary operator in Kotlin just like java?
No, we don’t have a ternary operator in Kotlin but you can use the functionality of ternary operator by using if-else or Elvis operator.
8. What is Elvis operator in Kotlin?
In Kotlin, you can assign null values to a variable by using the null safety property. To check if a value is having null value then you can use if-else or can use the Elvis operator i.e. ?:
For example:
var name:String? = "Mindorks"
val nameLength = name?.length ?: -1
println(nameLength)
The Elvis operator(?:
) used above will return the length of name if the value is not null otherwise if the value is null, then it will return -1
.
9. How to convert a Kotlin source file to a Java source file?
Steps to convert your Kotlin source file to Java source file:
- Open your Kotlin project in the IntelliJ IDEA / Android Studio.
- Then navigate to Tools > Kotlin > Show Kotlin Bytecode.
- Now click on the Decompile button to get your Java code from the bytecode.
10. What is the use of @JvmStatic, @JvmOverloads, and @JvmFiled in Kotlin?
- @JvmStatic: This annotation is used to tell the compiler that the method is a static method and can be used in Java code.
- @JvmOverloads: To use the default values passed as an argument in Kotlin code from the Java code, we need to use the
@JvmOverloads
annotation. - @JvmField: To access the fields of a Kotlin class from Java code without using any getters and setters, we need to use the
@JvmField
in the Kotlin code.
11. What is a data class in Kotlin?
Data classes are those classes which are made just to store some data. In Kotlin, it is marked as data. The following is an example of the same:
data class Developer(val name: String, val age: Int)
When we mark a class as a data class, you don’t have to implement or create the following functions like we do in Java: hashCode()
, equals()
, toString()
, copy()
. The compiler automatically creates these internally, so it also leads to clean code. Although, there are few other requirements that data classes need to fulfill.
12. Can we use primitive types such as int, double, float in Kotlin?
In Kotlin, we can’t use primitive types directly. We can use classes like Int, Double, etc. as an object wrapper for primitives. But the compiled bytecode has these primitive types.
13. What is String Interpolation in Kotlin?
If you want to use some variable or perform some operation inside a string then String Interpolation can be used. You can use the $
sign to use some variable in the string or can perform some operation in between {}
sign.
var name = "MindOrks"
print("Hello! I am learning from $name")
14. What do you mean by destructuring in Kotlin?
Destructuring is a convenient way of extracting multiple values from data stored in(possibly nested) objects and Arrays. It can be used in locations that receive data (such as the left-hand side of an assignment). Sometimes it is convenient to destructure an object into a number of variables, for example:
val (name, age) = developer
Now, we can use name and age independently like below:
println(name)
println(age)
15. When to use the lateinit keyword in Kotlin?
lateinit
is late initialization.
Normally, properties declared as having a non-null type must be initialized in the constructor. However, fairly often this is not convenient.
For example, properties can be initialized through dependency injection, or in the setup method of a unit test. In this case, you cannot supply a non-null initializer in the constructor, but you still want to avoid null checks when referencing the property inside the body of a class. To handle this case, you can mark the property with the lateinit modifier.
16. How to check if a lateinit variable has been initialized or not?
You can check if the lateinit variable has been initialized or not before using it with the help of isInitialized
method. This method will return true if the lateinit property has been initialized otherwise it will return false. For example:
class Person {
lateinit var name: String
fun initializeName() {
println(this::name.isInitialized)
name = "MindOrks" // initializing name
println(this::name.isInitialized)
}
}
fun main(args: Array<String>) {
Person().initializeName()
}
17. What is the difference between lateinit and lazy in Kotlin?
- lazy can only be used for val properties, whereas lateinit can only be applied to var because it can’t be compiled to a final field, thus no immutability can be guaranteed.
- If you want your property to be initialized from outside in a way probably unknown beforehand, use lateinit.
18. Is there any difference between == operator and === operator?
Yes. The ==
operator is used to compare the values stored in variables and the ===
operator is used to check if the reference of the variables are equal or not. But in the case of primitive types, the ===
operator also checks for the value and not reference.
// primitive example
val int1 = 10
val int2 = 10
println(int1 == int2) // true
println(int1 === int2) // true
// wrapper example
val num1 = Integer(10)
val num2 = Integer(10)
println(num1 == num2) // true
println(num1 === num2) //false
19. What is the forEach in Kotlin?
In Kotlin, to use the functionality of a for-each loop just like in Java, we use a forEach
function. The following is an example of the same:
var listOfMindOrks = listOf("mindorks.com", "blog.mindorks.com", "afteracademy.com")
listOfMindOrks.forEach {
Log.d(TAG,it)
}
20. What are companion objects in Kotlin?
In Kotlin, if you want to write a function or any member of the class that can be called without having the instance of the class then you can write the same as a member of a companion object inside the class.
To create a companion object, you need to add the companion
keyword in front of the object declaration.
The following is an example of a companion object in Kotlin:
class ToBeCalled {
companion object Test {
fun callMe() = println("You are calling me :)")
}
}
fun main(args: Array<String>) {
ToBeCalled.callMe()
}
21. What is the equivalent of Java static methods in Kotlin?
To achieve the functionality similar to Java static methods in Kotlin, we can use:
- companion object
- package-level function
- object
22. What is the difference between FlatMap and Map in Kotlin?
- FlatMap is used to combine all the items of lists into one list.
- Map is used to transform a list based on certain conditions.
23. What is the difference between List and Array types in Kotlin?
If you have a list of data that is having a fixed size, then you can use an Array. But if the size of the list can vary, then we have to use a mutable list.
24. Can we use the new keyword to instantiate a class object in Kotlin?
No, in Kotlin we don’t have to use the new
keyword to instantiate a class object. To instantiate a class object, simply we use:
var varName = ClassName()
25. What are visibility modifiers in Kotlin?
A visibility modifier or access specifier or access modifier is a concept that is used to define the scope of something in a programming language. In Kotlin, we have four visibility modifiers:
- private: visible inside that particular class or file containing the declaration.
- protected: visible inside that particular class or file and also in the subclass of that particular class where it is declared.
- internal: visible everywhere in that particular module.
- public: visible to everyone.
Note: By default, the visibility modifier in Kotlin is public.
26. How to create a Singleton class in Kotlin?
A singleton class is a class that is defined in such a way that only one instance of the class can be created and is used where we need only one instance of the class like in logging, database connections, etc.
To create a Singleton class in Kotlin, you need to use the object keyword.
object AnySingletonClassName
Note: You can’t use constructor in object, but you can use init.
27. What are init blocks in Kotlin?
init
blocks are initializer blocks that are executed just after the execution of the primary constructor. A class file can have one or more init blocks that will be executed in series. If you want to perform some operation in the primary constructor, then it is not possible in Kotlin, for that, you need to use the init
block.
28. What are the types of constructors in Kotlin?
- Primary constructor: These constructors are defined in the class header and you can’t perform some operation in it, unlike Java’s constructor.
- Secondary constructor: These constructors are declared inside the class body by using the constructor keyword. You must call the primary constructor from the secondary constructor explicitly. Also, the property of the class can’t be declared inside the secondary constructor. There can be more than one secondary constructors in Kotlin.
29. Is there any relationship between primary and secondary constructors?
Yes, when using a secondary constructor, you need to call the primary constructor explicitly.
30. What is the default type of argument used in a constructor?
By default, the type of arguments of a constructor in val. But you can change it to var explicitly.
31. What are Coroutines in Kotlin?
A framework to manage concurrency in a more performant and simple way with its lightweight thread which is written on top of the actual threading framework to get the most out of it by taking the advantage of cooperative nature of functions.
This is an important interview question.
32. What is suspend function in Kotlin Coroutines?
Suspend function is the building block of the Coroutines in Kotlin. Suspend function is a function that could be started, paused, and resume. To use a suspend function, we need to use the suspend keyword in our normal function definition.
33. What is the difference between Launch and Async in Kotlin Coroutines?
The difference is that the launch{}
does not return anything and the async{}
returns an instance of Deferred<T>
, which has an await()
function that returns the result of the coroutine like we have future in Java in which we do future.get()
to the get the result.
In other words:
- launch: fire and forget
- async: perform a task and return a result
36. How to choose between a switch and when in Kotlin?
Whenever we want to handle many if-else conditions, then we generally use switch-case statements. But Kotlin provides a more concise option i.e. in Kotlin, we can use when in place of the switch. And, when can be used as:
- expression
- arbitrary condition expression
- without argument
- with two or more choices
For example:
when(number) {
1 -> println("One")
2, 3 -> println("Two or Three")
4 -> println("Four")
else -> println("Number is not between 1 and 4")
}
37. What is the open keyword in Kotlin used for?
By default, the classes and functions are final in Kotlin. So, you can’t inherit the class or override the functions. To do so, you need to use the open keyword before the class and function. For example:
nheritance in Kotlin
In Kotlin, to inherit one class from the other, you can use the below syntax:
//Base Class
open class MindOrks {}//Derived class
class AndroidPro : MindOrks(){}
Here, in the above example, we are inheriting the class MindOrks from the class AndroidPro. So, MindOrks is the Parent class and AndroidPro is the Child class.
38. What are lambdas expressions?
Lambdas expressions are anonymous functions that can be treated as values i.e. we can pass the lambdas expressions as arguments to a function return them, or do any other thing we could do with a normal object. For example:
val add : (Int, Int) -> Int = { a, b -> a + b }
val result = add(9, 10)
Lambdas Expressions
Lambdas Expressions are essentially anonymous functions that we can treat as values — we can, for example, pass them as arguments to functions, return them, or do any other thing we could do with a normal object.
Lambda Expressions look like below:
val square : (Int) -> Int = { value -> value * value }val nine = square(3)
Now, let’s learn it by a simple example in Kotlin:
val doNothing : (Int) -> Int = { value -> value }
This is a lambda expression that does nothing. Here the
{ value -> value }
is a complete function in itself. It takes an int as a parameter and returns a value as an int
.
In (Int) -> Int
(Int)
represents input int
as a parameter.
Int
represents return type as an int
.
So, the doNothing
is a function in itself that takes a value as an int
and returns the same value as an int
.
Now another example:
val add : (Int, Int) -> Int = { a, b -> a + b }
This is also a lambda expression that takes two int
as the parameters, adds them, and returns as an int
.
{ a, b -> a + b }
is a function in itself that takes two int
as the parameters, adds them, and returns as an int.
In (Int, Int) -> Int
(Int, Int)
represents two int
as the input parameters.
39. What are Higher-Order functions in Kotlin?
A higher-order function is a function that takes functions as parameters or returns a function. For example, A function can take functions as parameters.
fun passMeFunction(abc: () -> Unit) {
// I can take function
// do something here
// execute the function
abc()
}
For example, A function can return another function.
fun add(a: Int, b: Int): Int {
return a + b
}
And, we have a function returnMeAddFunction which takes zero parameters and returns a function of the type ((Int, Int) -> Int).
fun returnMeAddFunction(): ((Int, Int) -> Int) {
// can do something and return function as well
// returning function
return ::add
}
And to call the above function, we can do:
val add = returnMeAddFunction()
val result = add(2, 2)
40. What are extension functions in Kotlin?
Extension functions are like extensive properties attached to any class in Kotlin. By using extension functions, you can add some methods or functionalities to an existing class even without inheriting the class. For example: Let’s say, we have views where we need to play with the visibility of the views. So, we can create an extension function for views like,
fun View.show() {
this.visibility = View.VISIBLE
}fun View.hide() {
this.visibility = View.GONE
}
and to use it we use, like,
toolbar.hide()
41. What is an infix function in Kotlin?
An infix function is used to call the function without using any bracket or parenthesis. You need to use the infix keyword to use the infix function.
class Operations {
var x = 10;
infix fun minus(num: Int) {
this.x = this.x - num
}
}
fun main() {
val opr = Operations()
opr minus 8
print(opr.x)
}
42. What is inline function?
Inline function instruct compiler to insert complete body of the function wherever that function got used in the code.
Advantages of inline function are as follows:
- Function call overhead doesn’t occur.
- It also saves the overhead of push/pop variables on the stack when the function is called.
- It also saves the overhead of a return call from a function. Such optimizations are not possible for normal function calls.
Let’s see it with an example
fun doSomething() {
print("doSomething start")
doSomethingElse()
print("doSomething end")
}fun doSomethingElse() {
print("doSomethingElse")
}
Here, we have the following two functions:
- doSomething()
- doSomethingElse()
Both are normal functions. doSomething() function is calling the doSomethingElse() function.
In order to understand it better, let’s see the decompiled code
In Android Studio. Go to: Tools -> Kotlin -> Show Kotlin Bytecode, then click the Decompile button.
The decompiled code is as below:
public void doSomething() {
System.out.print("doSomething start");
doSomethingElse();
System.out.print("doSomething end");
}public void doSomethingElse() {
System.out.print("doSomethingElse");
}
As we can see here, the doSomething() function is calling the doSomethingElse() function as usual.
Now let’s try to add the inline keyword as below in the doSomethingElse() function.
fun doSomething() {
print("doSomething start")
doSomethingElse()
print("doSomething end")
}inline fun doSomethingElse() {
print("doSomethingElse")
}
Again, let’s see the decompiled code. The decompiled code is as below:
public void doSomething() {
System.out.print("doSomething start");
System.out.print("doSomethingElse");
System.out.print("doSomething end");
}
Now, we can see that the code of doSomethingElse() function is copied inside the doSomething() function. And the doSomething() function is no more calling the doSomethingElse() function.
This is all because we have used the inline keyword.
So, when to make the function inline and when not:
- When the function code is very small, it’s good idea to make the function inline.
- When the function code is large and called from so many places, it’s a bad idea to make the function inline, as the large code will be repeated again and again.
43. What is noinline?
Assume that we have two lambdas as abc and xyz like below:
inline fun doSomethingElse(abc: () -> Unit, xyz: () -> Unit) {
// I can take function
// do something else here
// execute the function
abc()
xyz()
}
But, we do not want to inline both the lambdas abc and xyz, we just want to inline abc, but not the xyz, in this case, we need to use the noinline before the xyz like below:
inline fun doSomethingElse(abc: () -> Unit, noinline xyz: () -> Unit) {
// I can take function
// do something else here
// execute the function
abc()
xyz()
}
This way, we can use the noinline to avoid the inlining.
Now, we have understood what is noinline. Let’s move to the next one which is crossinline.
44. What are Reified types in Kotlin?
Since you are reading this blog, you must agree to the point that Kotlin is an awesome language and this is because of its unique features as compared to other programming languages. One of these features is the Reified keyword in Kotlin. Wait, what is this weird term called Reified? Don’t worry, that’s the topic for today’s blog. In this blog, we are going to learn about Reified types. So, let’s get started.
Before getting started
Most of the programming language has the concept of generics. Generics are used to provide a generic/general implementation of a class or a function or some properties i.e. you will write the implementation part once and use it for various data types.
For example, here is a code for a generic function:
fun <T> genericsExample(value: T) {
println(value)
}
fun main() {
genericsExample<String>("Learning Generics!")
genericsExample<Int>(100)
}
The above generic function can be used for any type of variable i.e for String, Int, Boolean, etc. So, the output of the above code will be:
Learning Generics!
100
Now, in the genericsExample
function, let's try to find the type of T
used i.e. let's have a print statement that will print if the type of T
is String, Int, Boolean or something else.
fun <T> genericsExample(value: T) {
println(value)
prinln("Type of T: ${T::class.java}")
}
Is the above code working fine? No, you will be getting Cannot use 'T' as reified type parameter
error. We can't get the info about the type T because of the type erasure thing in generics. So, if you want to access the type of T
, then we can pass the class of the T
as a parameter to the function genericsExample
.
fun <T> genericsExample(classType: Class<T>, value: T) {
println(value)
println("Type of T: ${classType}")
}
fun main() {
genericsExample<String>(String::class.java, "Learning Generics!")
genericsExample<Int>(Int::class.java, 100)
}
But is it the best way to do this? Is it ok to use a boilerplate code like this? No, absolutely not.
So, here comes the role of the reified keyword in Kotlin. Let’s learn about it.
45. What is the operator overloading in Kotlin?
In Kotlin, we can use the same operator to perform various tasks and this is known as operator overloading. To do so, we need to provide a member function or an extension function with a fixed name and operator keyword before the function name because normally also, when we are using some operator then under the hood some function gets called. For example, if you are writing num1+num2
, then it gets converted to num1.plus(num2)
.
For example:
fun main() {
val bluePen = Pen(inkColor = "Blue")
bluePen.showInkColor() val blackPen = Pen(inkColor = "Black")
blackPen.showInkColor() val blueBlackPen = bluePen + blackPen
blueBlackPen.showInkColor()
} operator fun Pen.plus(otherPen: Pen):Pen{
val ink = "$inkColor, ${otherPen.inkColor}"
return Pen(inkColor = ink)
} data class Pen(val inkColor:String){
fun showInkColor(){ println(inkColor)}
}
46.Explain the use-case of let, run, with, also, apply in Kotlin.
47. What are pair and triple in Kotlin?
Pair and Triples are used to return two and three values respectively from a function and the returned values can be of the same data type or different.
val pair = Pair("My Age: ", 25)
print(pair.first + pair.second)
48. What are labels in Kotlin?
Any expression written in Kotlin is called a label. For example, if we are having a for-loop in our Kotlin code then we can name that for-loop expression as a label and will use the label name for the for-loop.
We can create a label by using an identifier followed by the @
sign. For example, name@
, loop@
, xyz@
, etc. The following is an example of a label:
loop@ for (i in 1..10) {
// some code goes here
}
The name of the above for-loop is loop
.
49. What are the benefits of using a Sealed Class over Enum?
Sealed classes give us the flexibility of having different types of subclasses and also containing the state. The important point to be noted here is the subclasses that are extending the Sealed classes should be either nested classes of the Sealed class or should be declared in the same file as that of the Sealed class.
50. What are collections in Kotlin?
Ref: https://blog.mindorks.com/kotlin-android-interview-questions