Null safety, coroutines, data classes, sealed classes, collections, generics & Android basics
Languagefun main() {
println("Hello Kotlin!")
}
// Variables
val name = "Alice" // immutable (prefer val)
var age = 30 // mutable
val pi: Double = 3.14
// Types: Int, Long, Double, Float, Boolean, Char, String, Byte, Short
val x: Int = 42
val big: Long = 100_000_000L
val f: Float = 3.14f
val flag: Boolean = true
// String templates
val s: String = "Hello ${name}, age $age"
val multiline = """
|Multi-line
|string
""".trimMargin()
// Null safety
var nullable: String? = null
nullable?.length // safe call → null
nullable?.length ?: 0 // Elvis operator → 0
nullable!!.length // assert non-null (throws if null)
// Type checks & casts
if (obj is String) obj.length // smart cast
val str = obj as? String // safe cast (null if fails)
val str2 = obj as String // unsafe cast (throws ClassCastException)
// Constants
const val MAX = 100 // compile-time constant (top-level or companion)
// Type aliases
typealias UserMap = Map<String, List<Int>>
// Ranges
val r1 = 1..10 // 1 to 10 inclusive
val r2 = 1 until 10 // 1 to 9 (exclusive end)
val r3 = 10 downTo 1 // descending
val r4 = 1..10 step 2 // 1, 3, 5, 7, 9// if is an expression
val max = if (a > b) a else b
// when (replaces switch)
when (x) {
1 -> println("one")
2, 3 -> println("two or three")
in 4..10 -> println("4..10")
!in 0..20 -> println("out of range")
is String -> println("it's a string")
else -> println("other")
}
// when as expression (must be exhaustive)
val label = when {
score >= 90 -> "A"
score >= 80 -> "B"
else -> "C"
}
// for loops
for (i in 1..5) println(i)
for (i in 5 downTo 1 step 2) println(i)
for ((index, value) in list.withIndex()) println("$index: $value")
for ((key, value) in map) println("$key=$value")
// while / do-while
while (x > 0) { x-- }
do { x++ } while (x < 10)
// Labels & break/continue
outer@ for (i in 1..5) {
for (j in 1..5) {
if (j == 3) break@outer
}
}
// repeat
repeat(5) { i -> println("Iteration $i") }// Functions
fun add(a: Int, b: Int): Int = a + b // expression body
fun greet(name: String = "World") = println("Hello $name")
greet() // "Hello World"
greet(name = "Alice") // named argument
// vararg
fun sum(vararg nums: Int): Int = nums.sum()
sum(1, 2, 3)
sum(*intArrayOf(1,2,3)) // spread operator
// Infix functions
infix fun Int.times(str: String) = str.repeat(this)
3 times "Hi " // "Hi Hi Hi "
// Lambdas
val double = { x: Int -> x * 2 }
val nums = listOf(1,2,3)
nums.filter { it % 2 == 0 } // implicit 'it'
nums.map { it * 2 }
nums.reduce { acc, n -> acc + n }
// Higher-order functions
fun operate(a: Int, b: Int, op: (Int, Int) -> Int): Int = op(a, b)
operate(3, 4) { x, y -> x + y } // trailing lambda
// Function references
val ref = ::add // top-level function reference
val ref2 = String::length // member reference
listOf("a","bb").map(String::length)
// Inline functions (avoid lambda allocation overhead)
inline fun <reified T> isType(value: Any): Boolean = value is T
// Extension functions
fun String.addExclaim() = "$this!"
"Hello".addExclaim() // "Hello!"
// Scope functions
person.let { println(it.name) } // let: 'it' ref, returns result
person.apply { name = "Bob"; age = 25 } // apply: 'this' ref, returns receiver
person.also { log(it) } // also: 'it' ref, returns receiver
person.run { "$name is $age" } // run: 'this' ref, returns result
with(person) { println("$name $age") } // with: 'this' ref, returns result// Immutable (read-only) collections
val list = listOf(1, 2, 3)
val set = setOf("a", "b")
val map = mapOf("x" to 1, "y" to 2)
// Mutable collections
val mList = mutableListOf(1, 2)
mList.add(3); mList.removeAt(0); mList += 4
val mSet = mutableSetOf("a")
val mMap = mutableMapOf("x" to 1)
mMap["y"] = 2
// Array
val arr = arrayOf(1, 2, 3)
val intArr = intArrayOf(1, 2, 3)
val sized = Array(5) { i -> i * 2 } // [0,2,4,6,8]
// Collection operations
list.filter { it > 1 } // [2, 3]
list.map { it * 10 } // [10, 20, 30]
list.flatMap { listOf(it, it + 1) } // [1,2,2,3,3,4]
list.find { it > 1 } // 2 (first match or null)
list.any { it > 2 } // true
list.all { it > 0 } // true
list.none { it > 5 } // true
list.count { it > 1 } // 2
list.groupBy { it % 2 } // {1=[1,3], 0=[2]}
list.associate { it to it * 10 } // {1=10, 2=20, 3=30}
list.partition { it > 1 } // ([2,3], [1])
list.zip(listOf("a","b","c")) // [(1,a), (2,b), (3,c)]
list.chunked(2) // [[1,2], [3]]
list.windowed(2) // [[1,2], [2,3]]
list.fold(0) { acc, n -> acc + n } // 6
list.reduce { acc, n -> acc + n } // 6
list.sorted() // natural order
list.sortedByDescending { it }
list.take(2); list.drop(1)
list.distinct(); list.reversed()
// Map operations
map.keys; map.values; map.entries
map.getOrDefault("z", 0)
map.filter { (k, v) -> v > 1 }
map.mapValues { (_, v) -> v * 10 }
map.mapKeys { (k, _) -> k.uppercase() }
// Sequences (lazy evaluation)
list.asSequence()
.filter { it > 1 }
.map { it * 10 }
.toList()
generateSequence(1) { it * 2 }.take(5).toList() // [1,2,4,8,16]// Basic class
class Person(val name: String, var age: Int) {
init { println("Created $name") } // initializer block
constructor(name: String) : this(name, 0) // secondary constructor
}
// Data class (auto equals, hashCode, toString, copy, componentN)
data class User(val name: String, val age: Int)
val user = User("Alice", 30)
val copy = user.copy(age = 31)
val (name, age) = user // destructuring
// Sealed class (restricted hierarchy)
sealed class Result {
data class Success(val data: String) : Result()
data class Error(val msg: String) : Result()
object Loading : Result()
}
when (result) {
is Result.Success -> println(result.data)
is Result.Error -> println(result.msg)
Result.Loading -> println("Loading...")
}
// Sealed interface (Kotlin 1.5+)
sealed interface Shape
data class Circle(val r: Double) : Shape
data class Rect(val w: Double, val h: Double) : Shape
// Enum class
enum class Direction(val dx: Int, val dy: Int) {
UP(0,1), DOWN(0,-1), LEFT(-1,0), RIGHT(1,0);
fun opposite() = when(this) {
UP -> DOWN; DOWN -> UP; LEFT -> RIGHT; RIGHT -> LEFT
}
}
// Value class (inline wrapper, zero overhead)
@JvmInline
value class Email(val value: String)
// Object (singleton) & companion
object Database { fun connect() {} }
class MyClass {
companion object {
fun create() = MyClass() // like static
}
}
// Inheritance
open class Animal(val name: String) {
open fun sound() = "..."
}
class Dog(name: String) : Animal(name) {
override fun sound() = "Woof!"
}
// Interface
interface Drawable {
fun draw()
fun description() = "Drawable object" // default implementation
}
// Abstract class
abstract class Vehicle {
abstract val speed: Int
fun info() = "Speed: $speed"
}
// Delegation
class CountingSet<T>(
val inner: MutableSet<T> = mutableSetOf()
) : MutableSet<T> by inner {
var addCount = 0
override fun add(elem: T): Boolean { addCount++; return inner.add(elem) }
}// Generic class
class Box<T>(val value: T)
val box = Box("hello") // Box<String> inferred
// Generic function
fun <T> singletonList(item: T): List<T> = listOf(item)
// Bounded generics
fun <T : Comparable<T>> sort(list: List<T>) { }
// Multiple bounds
fun <T> copy(item: T) where T : Serializable, T : Comparable<T> { }
// Variance
class Producer<out T>(val value: T) // covariant (out = producer)
class Consumer<in T> { fun consume(item: T) {} } // contravariant
// Star projection (like Java's ?)
fun printAll(list: List<*>) { list.forEach { println(it) } }
// Reified type parameters (inline only)
inline fun <reified T> isA(value: Any) = value is T
isA<String>("hi") // trueimport kotlinx.coroutines.*
// Launch (fire and forget)
fun main() = runBlocking {
launch {
delay(1000)
println("World!")
}
println("Hello")
}
// Async (returns result via Deferred)
val deferred = async { fetchData() }
val result = deferred.await()
// Parallel execution
coroutineScope {
val a = async { fetchUser() }
val b = async { fetchPosts() }
println("${a.await()} ${b.await()}")
}
// Dispatchers
launch(Dispatchers.IO) { } // I/O operations (network, disk)
launch(Dispatchers.Default) { } // CPU-intensive work
launch(Dispatchers.Main) { } // UI thread (Android)
launch(Dispatchers.Unconfined) { } // starts in caller thread
// withContext (switch dispatcher)
suspend fun fetchData(): String = withContext(Dispatchers.IO) {
// network call here
"data"
}
// Structured concurrency & cancellation
val job = launch {
repeat(1000) { i ->
println("job: $i")
delay(500) // cancellable suspension point
}
}
delay(1300)
job.cancelAndJoin() // cancel and wait for completion
// Timeout
withTimeout(3000) { /* throws TimeoutCancellationException */ }
withTimeoutOrNull(3000) { /* returns null on timeout */ }
// Flow (cold reactive stream)
fun numbers(): Flow<Int> = flow {
for (i in 1..5) {
delay(100)
emit(i)
}
}
numbers()
.filter { it % 2 == 0 }
.map { it * 10 }
.collect { println(it) }
// StateFlow & SharedFlow
val state = MutableStateFlow(0) // hot, holds latest value
state.value = 42
state.collect { println(it) }
val shared = MutableSharedFlow<String>() // hot, no initial value
shared.emit("event")
// Flow operators
flow.onEach { log(it) }
flow.catch { e -> emit(fallback) }
flow.onCompletion { cause -> /* cleanup */ }
flow.debounce(300)
flow.distinctUntilChanged()
flow.combine(otherFlow) { a, b -> a + b }
flow.flatMapLatest { fetchDetails(it) }// try/catch/finally
try {
val result = riskyOperation()
} catch (e: IOException) {
println("IO error: ${e.message}")
} catch (e: Exception) {
println("Error: ${e.message}")
} finally {
cleanup()
}
// try is an expression
val number = try { str.toInt() } catch (e: NumberFormatException) { 0 }
// throw is an expression (return type: Nothing)
val name = person.name ?: throw IllegalArgumentException("Name required")
// Custom exceptions
class ApiException(message: String, val code: Int) : Exception(message)
// require / check / error (preconditions)
require(age >= 0) { "Age must be non-negative" } // IllegalArgumentException
check(isInitialized) { "Not initialized" } // IllegalStateException
error("Something went wrong") // IllegalStateException
// Result type (functional error handling)
val result = runCatching { riskyCall() }
result.isSuccess
result.isFailure
result.getOrNull()
result.getOrDefault("fallback")
result.getOrElse { e -> "Error: ${e.message}" }
result.onSuccess { data -> process(data) }
.onFailure { e -> log(e) }
result.map { it.uppercase() }
result.recover { e -> "recovered" }// Property delegates
val lazyVal by lazy { expensiveCompute() } // computed once on first access
var observed by Delegates.observable("initial") { _, old, new ->
println("Changed from $old to $new")
}
var validated by Delegates.vetoable(0) { _, _, new ->
new >= 0 // reject negative values
}
// Map delegation
class Config(val map: Map<String, Any?>) {
val name: String by map
val age: Int by map
}
val config = Config(mapOf("name" to "Alice", "age" to 30))
// Type-safe builders (DSL)
fun html(block: HTML.() -> Unit): HTML = HTML().apply(block)
html {
head { title("Page") }
body {
p("Hello World")
ul {
listOf("a","b","c").forEach { li(it) }
}
}
}
// @DslMarker (restricts scope leaking)
@DslMarker
annotation class HtmlDsl
// Operator overloading
data class Point(val x: Int, val y: Int) {
operator fun plus(other: Point) = Point(x + other.x, y + other.y)
operator fun times(scale: Int) = Point(x * scale, y * scale)
}
Point(1,2) + Point(3,4) // Point(4, 6)// ── Jetpack Compose ──
// Composable function
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(text = "Hello $name!", modifier = modifier)
}
// State management
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("Count: $count")
}
}
// Common Compose layouts
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
Text("Title", style = MaterialTheme.typography.headlineMedium)
Spacer(modifier = Modifier.height(8.dp))
Row(horizontalArrangement = Arrangement.SpaceBetween) {
Icon(Icons.Default.Home, contentDescription = "Home")
Text("Home")
}
LazyColumn {
items(users) { user -> UserCard(user) }
}
}
// Navigation (Compose)
val navController = rememberNavController()
NavHost(navController, startDestination = "home") {
composable("home") { HomeScreen(navController) }
composable("detail/{id}") { backStackEntry ->
DetailScreen(backStackEntry.arguments?.getString("id"))
}
}
navController.navigate("detail/42")
// ── ViewModel ──
class MainViewModel : ViewModel() {
private val _uiState = MutableStateFlow(UiState())
val uiState = _uiState.asStateFlow()
fun loadData() {
viewModelScope.launch {
_uiState.value = UiState(loading = true)
val data = repository.fetchData()
_uiState.value = UiState(data = data)
}
}
}
// Collecting state in Compose
@Composable
fun Screen(viewModel: MainViewModel = viewModel()) {
val uiState by viewModel.uiState.collectAsState()
when {
uiState.loading -> CircularProgressIndicator()
uiState.error != null -> Text("Error: ${uiState.error}")
else -> DataList(uiState.data)
}
}
// ── Room Database ──
@Entity("users")
data class UserEntity(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
val name: String,
val email: String
)
@Dao
interface UserDao {
@Query("SELECT * FROM users")
fun getAll(): Flow<List<UserEntity>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(user: UserEntity)
@Delete
suspend fun delete(user: UserEntity)
}
// ── Retrofit (Networking) ──
interface ApiService {
@GET("users/{id}")
suspend fun getUser(@Path("id") id: Int): User
@POST("users")
suspend fun createUser(@Body user: User): Response<User>
}
val retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
// ── Hilt Dependency Injection ──
@HiltAndroidApp
class MyApp : Application()
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides @Singleton
fun provideApi(): ApiService = retrofit.create(ApiService::class.java)
}
@HiltViewModel
class MainViewModel @Inject constructor(
private val api: ApiService
) : ViewModel() { }// ── Kotlin Multiplatform (KMP) ──
// Share code between Android, iOS, Desktop, Web
// Shared module — expect/actual pattern
// commonMain/
expect fun platformName(): String
fun greet() = "Hello from ${platformName()}"
// androidMain/
actual fun platformName() = "Android"
// iosMain/
actual fun platformName() = "iOS"
// Shared ViewModel with KMP
class SharedViewModel {
private val _state = MutableStateFlow(UiState())
val state = _state.asStateFlow()
fun loadItems() {
coroutineScope.launch {
val items = repository.getItems()
_state.value = UiState(items = items)
}
}
}
// ── Ktor (Server-Side Kotlin) ──
fun main() {
embeddedServer(Netty, port = 8080) {
install(ContentNegotiation) { json() }
install(StatusPages) {
exception<Throwable> { call, cause ->
call.respondText(cause.message ?: "Error",
status = HttpStatusCode.InternalServerError)
}
}
routing {
get("/") { call.respondText("Hello, Ktor!") }
get("/users/{id}") {
val id = call.parameters["id"]?.toIntOrNull()
val user = userService.findById(id!!)
call.respond(user)
}
post("/users") {
val user = call.receive<User>()
userService.create(user)
call.respond(HttpStatusCode.Created, user)
}
}
}.start(wait = true)
}
// Ktor Client (shared across platforms)
val client = HttpClient {
install(ContentNegotiation) { json() }
install(Logging) { level = LogLevel.INFO }
}
val response: User = client.get("https://api.example.com/users/1").body()
// ── Kotlin/JS ──
fun main() {
document.getElementById("root")?.innerHTML = "Hello from Kotlin/JS"
}
// Kotlin/JS interop with JavaScript
external fun alert(message: String)
external interface JsUser {
val name: String
val age: Int
}
// ── Compose Multiplatform ──
// UI framework for Android, iOS, Desktop, Web
@Composable
fun App() {
MaterialTheme {
var text by remember { mutableStateOf("Hello, World!") }
Button(onClick = { text = "Clicked!" }) {
Text(text)
}
}
}
// ── Kotlinx Serialization ──
@Serializable
data class User(val name: String, val age: Int)
val json = Json.encodeToString(User("Alice", 30))
val user = Json.decodeFromString<User>(json)
// ── Gradle Kotlin DSL (build.gradle.kts) ──
plugins {
kotlin("multiplatform") version "2.0.0"
id("org.jetbrains.compose")
}
kotlin {
androidTarget()
iosArm64()
js(IR) { browser() }
sourceSets {
commonMain.dependencies {
implementation(compose.runtime)
implementation(compose.material3)
implementation("io.ktor:ktor-client-core:2.3.0")
}
}
}