0% found this document useful (0 votes)
10 views

5 Basic Kotlin Interview Questions With Answers

The document presents five basic Kotlin interview questions along with detailed answers. It covers topics such as the advantages of Kotlin over Java, the differences between 'val' and 'var', nullable types and their safe handling, data classes and their benefits, and extension functions. Each section includes code examples to illustrate the concepts discussed.

Uploaded by

rajuabhi.ai
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

5 Basic Kotlin Interview Questions With Answers

The document presents five basic Kotlin interview questions along with detailed answers. It covers topics such as the advantages of Kotlin over Java, the differences between 'val' and 'var', nullable types and their safe handling, data classes and their benefits, and extension functions. Each section includes code examples to illustrate the concepts discussed.

Uploaded by

rajuabhi.ai
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

5 Basic Kotlin Interview Questions with Answers

1. What is Kotlin and what are its key advantages over Java?
Answer: Kotlin is a statically typed programming language developed by JetBrains that runs on the Java
Virtual Machine (JVM). It's 100% interoperable with Java and has been Google's preferred language for
Android development since 2019.

Key Advantages:

Conciseness:

kotlin

// Java
public class Person {
private String name;
private int age;

public Person(String name, int age) {


this.name = name;
this.age = age;
}

public String getName() { return name; }


public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}

// Kotlin
data class Person(var name: String, var age: Int)

Null Safety:

kotlin

var name: String = "John" // Non-nullable


var nullable: String? = null // Nullable
println(name.length) // Safe
println(nullable?.length) // Safe call operator

Other advantages:
Type Inference: Automatically determines variable types

Extension Functions: Add functionality to existing classes


Coroutines: Built-in support for asynchronous programming

Smart Casting: Automatic type casting after null checks


Default Parameters: Reduce method overloading

2. Explain the difference between val and var in Kotlin. When would you use
each?
Answer: val and var are used to declare variables in Kotlin, but they have different mutability
characteristics.

val (Value - Immutable Reference):

kotlin

val name = "John" // Type inferred as String


val age: Int = 25 // Explicit type declaration
// name = "Jane" // Compilation error - cannot reassign

val list = mutableListOf(1, 2, 3)


list.add(4) // OK - the list content can change
// list = mutableListOf() // Error - cannot reassign the reference

var (Variable - Mutable Reference):

kotlin

var count = 0 // Can be reassigned


count = 10 // OK
count++ // OK

var message: String? = null


message = "Hello" // OK - can reassign

When to use each:

Use val when:

The reference should not change after initialization

You want immutability (preferred for functional programming)


Declaring constants or configuration values

Following the principle of "prefer immutability"

Use var when:

The value needs to change during execution

Working with counters, accumulators, or state variables

The variable represents mutable state

Best Practice:

kotlin

// Prefer val by default


val users = getUsersFromDatabase()
val currentUser = users.find { it.id == userId }

// Use var only when necessary


var attempts = 0
while (attempts < maxAttempts && !isSuccessful()) {
attempts++
tryOperation()
}

3. What are nullable types in Kotlin and how do you handle null safely?
Answer: Kotlin's type system distinguishes between nullable and non-nullable types to eliminate null
pointer exceptions at compile time.

Nullable vs Non-nullable Types:

kotlin

var name: String = "John" // Non-nullable - cannot be null


var nickname: String? = null // Nullable - can be null

// name = null // Compilation error


nickname = null // OK

Safe Null Handling Techniques:

1. Safe Call Operator ( ?. ):


kotlin

val length = nickname?.length // Returns null if nickname is null


println(nickname?.uppercase()) // Only calls if not null

2. Elvis Operator ( ?: ):

kotlin

val displayName = nickname ?: "Unknown" // Use default if null


val length = nickname?.length ?: 0 // Chain with safe call

3. Safe Cast Operator ( as? ):

kotlin

val stringValue = someObject as? String // Returns null if cast fails

4. Not-null Assertion ( !! ):

kotlin

val length = nickname!!.length // Throws exception if null - use carefully!

5. let function for null checks:

kotlin

nickname?.let { name ->


println("Nickname is: $name")
// This block only executes if nickname is not null
}

6. Traditional null checks:

kotlin

if (nickname != null) {
println(nickname.length) // Smart cast - treated as non-null
}

Best Practices:
kotlin

// Good: Safe handling


fun processUser(user: User?) {
val email = user?.email ?: return
val domain = email.substringAfter("@").takeIf { it.isNotEmpty() } ?: "unknown"
println("User domain: $domain")
}

// Avoid: Overusing not-null assertion


fun badExample(user: User?) {
println(user!!.name) // Dangerous - can crash
}

4. Explain Kotlin data classes and their benefits. How do they differ from
regular classes?
Answer: Data classes in Kotlin are classes designed to hold data. They automatically generate useful
methods and provide concise syntax for creating classes that primarily store state.

Basic Data Class:

kotlin

data class User(


val id: Int,
val name: String,
val email: String,
var isActive: Boolean = true // Default parameter
)

Auto-generated Methods:
kotlin

val user1 = User(1, "John", "[email protected]")


val user2 = User(1, "John", "[email protected]")

// toString() - automatically generated


println(user1) // User(id=1, name=John, [email protected], isActive=true)

// equals() and hashCode() - based on primary constructor parameters


println(user1 == user2) // true (structural equality)
println(user1 === user2) // false (referential equality)

// copy() - create copies with some properties changed


val inactiveUser = user1.copy(isActive = false)
val renamedUser = user1.copy(name = "Jane")

// componentN() functions for destructuring


val (id, name, email) = user1
println("User $name has ID $id")

Comparison with Regular Classes:

Regular Class:
kotlin

class RegularUser(val id: Int, val name: String, val email: String) {
// Must manually implement if needed
override fun toString(): String {
return "RegularUser(id=$id, name=$name, email=$email)"
}

override fun equals(other: Any?): Boolean {


if (this === other) return true
if (other !is RegularUser) return false
return id == other.id && name == other.name && email == other.email
}

override fun hashCode(): String {


return Objects.hash(id, name, email)
}

// No copy() method available


// No destructuring support
}

Data Class Requirements:

Must have at least one parameter in primary constructor

All primary constructor parameters must be val or var

Cannot be abstract, open, sealed, or inner

Can implement interfaces and extend classes (with restrictions)

Benefits:

1. Less Boilerplate: Automatic generation of common methods

2. Consistency: Standard implementations of equals/hashCode

3. Immutability Support: Encourages use of val properties

4. Copy Functionality: Easy object copying with modifications

5. Destructuring: Convenient property extraction

6. Readable toString(): Automatic string representation

Advanced Usage:
kotlin

data class Product(


val id: String,
val name: String,
val price: Double,
val category: String
) {
// Additional methods can still be added
fun discountedPrice(discountPercent: Double): Double {
return price * (1 - discountPercent / 100)
}

// Properties not in constructor don't participate in equals/hashCode


val displayName: String get() = name.uppercase()
}

// Usage
val products = listOf(
Product("1", "Laptop", 999.99, "Electronics"),
Product("2", "Mouse", 29.99, "Electronics")
)

// Destructuring in loops
for ((id, name, price) in products) {
println("$name costs $price")
}

5. What are Kotlin extension functions and how do you create them? Provide
examples.
Answer: Extension functions allow you to add new functionality to existing classes without modifying
their source code or using inheritance. They appear to be part of the class but are actually resolved
statically.

Basic Extension Function Syntax:


kotlin

// Extend String class with a function to count words


fun String.wordCount(): Int {
return this.split("\\s+".toRegex()).size
}

// Usage
val text = "Hello world from Kotlin"
println(text.wordCount()) // Output: 4

Extension Function Components:

kotlin

fun ReceiverType.functionName(parameters): ReturnType {


// 'this' refers to the receiver object
// Function body
}

Examples:

1. Extending Built-in Classes:

kotlin

// Extension for Int


fun Int.isEven(): Boolean = this % 2 == 0

// Extension for List


fun <T> List<T>.secondOrNull(): T? = if (size >= 2) this[1] else null

// Usage
println(42.isEven()) // true
println(listOf(1, 2, 3).secondOrNull()) // 2
println(listOf(1).secondOrNull()) // null

2. Extending Custom Classes:


kotlin

data class Person(val firstName: String, val lastName: String, val age: Int)

// Extension function
fun Person.fullName(): String = "$firstName $lastName"

// Extension property
val Person.isAdult: Boolean
get() = age >= 18

// Usage
val person = Person("John", "Doe", 25)
println(person.fullName()) // John Doe
println(person.isAdult) // true

3. Generic Extension Functions:

kotlin

// Extension for any nullable type


fun <T> T?.isNotNull(): Boolean = this != null

// Extension for collections


fun <T> Collection<T>.isNotNullOrEmpty(): Boolean = !this.isNullOrEmpty()

// Usage
val name: String? = null
println(name.isNotNull()) // false

val list = listOf(1, 2, 3)


println(list.isNotNullOrEmpty()) // true

4. Practical Examples:
kotlin

// Date formatting extension


fun Long.toDateString(): String {
val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
return formatter.format(Date(this))
}

// String validation extensions


fun String.isValidEmail(): Boolean {
return android.util.Patterns.EMAIL_ADDRESS.matcher(this).matches()
}

fun String.isValidPhoneNumber(): Boolean {


return this.matches(Regex("^\\+?[1-9]\\d{1,14}$"))
}

// Usage
val timestamp = System.currentTimeMillis()
println(timestamp.toDateString()) // 2024-01-15

val email = "[email protected]"


println(email.isValidEmail()) // true

Important Characteristics:

1. Static Resolution:

kotlin

open class Shape


class Rectangle : Shape()

fun Shape.getName() = "Shape"


fun Rectangle.getName() = "Rectangle"

val shape: Shape = Rectangle()


println(shape.getName()) // "Shape" - resolved based on compile-time type

2. Member Functions Take Precedence:


kotlin

class Example {
fun existing() = "Member function"
}

fun Example.existing() = "Extension function" // Will be ignored

val example = Example()


println(example.existing()) // "Member function"

3. Extension Properties:

kotlin

// Extension property (must have getter)


val String.lastChar: Char
get() = this[length - 1]

var StringBuilder.lastChar: Char


get() = this[length - 1]
set(value) { this.setCharAt(length - 1, value) }

// Usage
println("Hello".lastChar) // 'o'

Best Practices:

Use extensions to add utility functions to existing types

Keep extensions simple and focused


Consider creating extension files organized by functionality

Use meaningful names that clearly indicate the extension's purpose


Be careful with nullable receiver types

You might also like