Progress Β· 0/10 sections
π’ π’ Kotlin Basics & Fundamentals
5 min read Β· Notion
π§ Core Language
What is Kotlin? How is it different from Java?
Kotlin is a statically typed, JVM-targeting language developed by JetBrains. Key differences from Java:
- Null Safety: Kotlin distinguishes nullable (
String?) and non-nullable (String) types at the compiler level. - Conciseness: Data classes, extension functions, and smart casts eliminate boilerplate.
- Coroutines: First-class async/concurrency support.
- No checked exceptions: Kotlin does not force you to catch exceptions.
- Functional programming: Lambdas, higher-order functions, and collection operators are idiomatic.
- Interoperability: 100% compatible with Java β you can call Java code from Kotlin and vice versa.
What is null safety in Kotlin?
Kotlin's type system distinguishes nullable from non-nullable types at compile time:
var a: String = "hello" // cannot be null
var b: String? = null // can be null
b?.length // safe call β returns null if b is null
b ?: "default" // Elvis operator β fallback value
b!!.length // non-null assertion β throws NPE if nullThis eliminates most NullPointerExceptions at compile time.
val vs var
val= immutable reference (like Javafinal). The object itself can still be mutated.var= mutable reference, can be reassigned.
val x = 10 // cannot reassign x
var y = 20 // y can be reassigned
y = 30 // OKWhat is the Elvis operator ?:?
The Elvis operator provides a default value when an expression is null:
val length = name?.length ?: 0
// If name is null, length = 0; otherwise length = name.lengthWhat are extension functions?
Extension functions let you add methods to existing classes without inheriting from them:
fun String.isPalindrome(): Boolean {
return this == this.reversed()
}
"racecar".isPalindrome() // trueThey're resolved statically and don't modify the original class.
What is a data class?
A data class auto-generates equals(), hashCode(), toString(), copy(), and componentN() functions:
data class User(val name: String, val age: Int)
val u1 = User("Ashu", 28)
val u2 = u1.copy(age = 29)Best for immutable value objects, DTOs, and domain models.
Sealed class vs Enum class
Enum: Fixed set of constant instances, all of the same type.
Sealed class: Fixed set of subclasses, each can hold different data. Great for modeling states.
sealed class Result<out T> {
data class Success<T>(val data: T) : Result<T>()
data class Error(val message: String) : Result<Nothing>()
object Loading : Result<Nothing>()
}Use sealed classes when subclasses need to carry different payloads.
What is a companion object?
A companion object is a singleton tied to a class β it replaces Java's static members:
class MyClass {
companion object {
const val TAG = "MyClass"
fun create() = MyClass()
}
}
MyClass.TAG
MyClass.create()Scope functions: let, apply, also, run, with
| Function | Receiver | Returns | Common Use |
|---|---|---|---|
let | it | Lambda result | Null checks, transformations |
apply | this | Receiver object | Object configuration / builder |
also | it | Receiver object | Side effects, logging |
run | this | Lambda result | Execute block, compute result |
with | this | Lambda result | Call multiple methods on object |
val user = User().apply {
name = "Ashu"
age = 28
}
user?.let { println(it.name) }π Higher-Order Functions & Lambdas
What is a higher-order function?
A function that takes a function as parameter or returns a function:
fun operate(x: Int, y: Int, op: (Int, Int) -> Int): Int = op(x, y)
operate(3, 4) { a, b -> a + b } // 7What is an inline function?
Inline functions copy their body to the call site at compile time, eliminating lambda object allocation overhead:
inline fun measure(block: () -> Unit) {
val start = System.nanoTime()
block()
println(System.nanoTime() - start)
}Use for small functions that accept lambdas to reduce memory pressure.
Difference between inline, noinline, and crossinline
inline: The entire lambda is inlined at call site.noinline: Prevents a specific lambda parameter from being inlined (when you want to store it).crossinline: Allows inlining but prevents non-local returns inside the lambda.
inline fun example(inlined: () -> Unit, noinline notInlined: () -> Unit) {
inlined() // inlined
notInlined() // stored as object
}Lazy vs lateinit
lazy: Value is computed once on first access. Thread-safe by default. Used withval.lateinit: Mutablevarthat will be assigned before use. Not null-safe β throws if accessed before init.
val config: Config by lazy { loadConfig() }
lateinit var binding: ActivityMainBindingUse lazy for read-only computed values; lateinit for DI-injected or lifecycle-bound mutable references.
π Collections
Mutable vs Immutable collections
Kotlin separates read-only interfaces (List, Set, Map) from mutable ones (MutableList, MutableSet, MutableMap):
val list = listOf(1, 2, 3) // read-only
val mutableList = mutableListOf(1, 2) // mutable
mutableList.add(3)Read-only collections are not thread-safe β use ConcurrentHashMap or coroutine-friendly structures for shared state.
map, filter, reduce, flatMap
val nums = listOf(1, 2, 3, 4, 5)
nums.filter { it % 2 == 0 } // [2, 4]
nums.map { it * 2 } // [2, 4, 6, 8, 10]
nums.reduce { acc, it -> acc + it } // 15
listOf(listOf(1,2), listOf(3,4)).flatMap { it } // [1, 2, 3, 4]flatMap maps each element to a collection and flattens the result into a single list.
What is the Result class in Kotlin?
Result<T> is a standard library class that models success or failure:
val result = runCatching { riskyOperation() }
result.onSuccess { println(it) }
result.onFailure { println(it.message) }Great alternative to try/catch chains in functional-style code.