Modern language for Android, servers, and multiplatform. Null-safe, concise, and interoperable with Java.
fun main() is the entry point. val for immutable, var for mutable. No semicolons needed.
fun main() {
println("Hello, World!")
val name = "Mayank" // immutable
var age = 15 // mutable
println("$name is $age")
println("${name.uppercase()}")
}
val/var, String, Int, Double, Boolean, List, Map. Kotlin is null-safe by default.
fun main() {
val name: String = "Mayank"
val age: Int = 15
val pi: Double = 3.14159
val passed: Boolean = true
// Null safety
var safe: String = "hello" // can't be null
var nullable: String? = null // can be null
println(nullable?.uppercase() ?: "null")
println(nullable!!.uppercase()) // will throw if null
// Collections
val nums = listOf(1, 2, 3, 4, 5)
val mutable = mutableListOf(1, 2)
mutable.add(3)
val map = mapOf("a" to 1, "b" to 2)
println(map["a"])
}
fun add(a: Int, b: Int): Int = a + b
fun greet(name: String, prefix: String = "Hello") = "$prefix, $name!"
// Lambda
val square = { x: Int -> x * x }
val multiply = { a: Int, b: Int -> a * b }
// High-order function
fun apply(n: Int, f: (Int) -> Int): Int = f(n)
fun main() {
println(add(3, 4))
println(greet("Mayank"))
println(greet("World", "Hi"))
println(square(5))
println(apply(10, square))
val nums = listOf(1, 2, 3, 4, 5)
println(nums.filter { it % 2 == 0 })
println(nums.map { it * 10 })
println(nums.reduce { a, b -> a + b })
}
if/else returns values. when is a super switch. for-in, while. Ranges (1..10, 1 until 10).
fun main() {
val score = 85
val grade = if (score >= 90) "A" else if (score >= 80) "B" else "C"
println(grade)
// when (switch on steroids)
val day = 3
when (day) {
1 -> println("Monday")
2 -> println("Tuesday")
3 -> println("Wednesday")
in 6..7 -> println("Weekend")
else -> println("Other")
}
// Ranges
for (i in 1..5) print("$i ")
println()
for (i in 1 until 10 step 2) print("$i ")
println()
// Destructuring
data class Point(val x: Int, val y: Int)
val p = Point(3, 4)
val (x, y) = p
println("($x, $y)")
}
fun main() {
var name: String? = null
// Safe call
println(name?.length) // null
// Elvis operator
println(name?.length ?: 0) // 0
// Non-null assertion (crashes if null!)
// println(name!!.length) // NullPointerException
// let (only runs if not null)
name = "Mayank"
name?.let {
println("Length: ${it.length}")
}
// require / check
fun validate(age: Int) {
require(age > 0) { "Age must be positive" }
require(age < 150) { "Age too high" }
println("Valid age: $age")
}
validate(15)
// Smart cast after check
val obj: Any = "hello"
if (obj is String) {
println(obj.length) // auto-cast to String
}
}
data class auto-generates equals/hashCode/toString. sealed class for restricted hierarchies.
data class Point(val x: Double, val y: Double) {
fun distanceTo(other: Point) =
Math.sqrt((x-other.x).pow(2) + (y-other.y).pow(2))
}
sealed class Result {
data class Success(val data: String) : Result()
data class Error(val msg: String) : Result()
}
fun main() {
val p1 = Point(0.0, 0.0)
val p2 = Point(3.0, 4.0)
println(p1) // Point(x=0.0, y=0.0)
println(p1.distanceTo(p2)) // 5.0
val r: Result = Result.Success("ok")
when (r) {
is Result.Success -> println(r.data)
is Result.Error -> println(r.msg)
}
}
open class (not final by default). Interface with default implementations. Abstract classes.
open class Animal(val name: String) {
open fun speak() = "..."
}
class Dog(name: String) : Animal(name) {
override fun speak() = "Woof!"
}
class Cat(name: String) : Animal(name) {
override fun speak() = "Meow!"
}
interface Swimmable {
fun swim() = println("Swimming!")
}
class Fish(name: String) : Animal(name), Swimmable
fun main() {
val animals = listOf(Dog("Rex"), Cat("Whiskers"), Fish("Nemo"))
for (a in animals) println("${a.name}: ${a.speak()}")
val fish = Fish("Nemo")
fish.swim()
}
class Stack<T> {
private val items = mutableListOf<T>()
fun push(item: T) { items.add(item) }
fun pop(): T? = items.removeLastOrNull()
fun peek(): T? = items.lastOrNull()
}
fun <T> findMax(list: List<T>): T where T : Comparable<T> {
return list.max()
}
inline fun <reified T> List<Any>.filterType(): List<T> {
return filterIsInstance<T>()
}
fun main() {
val stack = Stack<Int>()
stack.push(1)
stack.push(2)
println(stack.pop())
println(findMax(listOf(3, 1, 4, 1, 5)))
val mixed = listOf(1, "hello", 3.14, "world")
println(mixed.filterType<String>()) // [hello, world]
}
Add methods to existing classes without modifying them. infix functions. operator overloading.
// Extension function
fun String.isPalindrome(): Boolean {
val s = this.lowercase()
return s == s.reversed()
}
fun Int.isEven() = this % 2 == 0
// Infix function
infix fun Int.power(exponent: Int): Long {
var result = 1L
repeat(exponent) { result *= this }
return result
}
// Operator overloading
data class Vec2(val x: Int, val y: Int) {
operator fun plus(other: Vec2) = Vec2(x + other.x, y + other.y)
operator fun times(s: Int) = Vec2(x * s, y * s)
}
fun main() {
println("racecar".isPalindrome())
println(42.isEven())
println(2 power 10) // 1024
println(Vec2(1,2) + Vec2(3,4)) // Vec2(x=4, y=6)
}
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
suspend fun fetchUser(): String {
delay(1000)
return "Mayank"
}
fun numberFlow() = flow {
for (i in 1..5) {
delay(500)
emit(i)
}
}
fun main() = runBlocking {
// Launch concurrent
val job = launch {
val user = fetchUser()
println("User: $user")
}
// Async
val deferred = async { 42 * 42 }
println("Result: ${deferred.await()}")
// Flow
numberFlow()
.filter { it % 2 == 0 }
.map { it * 10 }
.collect { println(it) }
job.join()
}
Kotlin's killer feature. Build HTML, SQL, configs with type-safe builders.
// HTML builder
class HTML {
private val sb = StringBuilder()
fun body(init: HTML.() -> Unit) {
sb.append("<body>")
init()
sb.append("</body>")
}
fun p(text: String) { sb.append("<p>$text</p>") }
override fun toString() = sb.toString()
}
fun html(init: HTML.() -> Unit) = HTML().apply(init)
fun main() {
val page = html {
body {
p("Hello, World!")
p("Kotlin DSLs are awesome")
}
}
println(page)
// Scope functions
data class Config(var host: String = "", var port: Int = 0)
val config = Config().apply {
host = "localhost"
port = 8080
}
println(config)
}
Share code between iOS, Android, web, desktop. Ktor for servers. Compose for UI.
// Ktor server (build.gradle.kts)
// implementation("io.ktor:ktor-server-core:2.3.0")
// implementation("io.ktor:ktor-server-netty:2.3.0")
fun main() = embeddedServer(Netty, port = 8080) {
routing {
get("/") { call.respondText("Hello, Ktor!") }
get("/users") {
call.respond(mapOf("users" to listOf("Mayank")))
}
}
}.start(wait = true)
// Compose Multiplatform
// @Composable
// fun App() {
// var count by remember { mutableStateOf(0) }
// Column {
// Text("Count: $count")
// Button(onClick = { count++ }) { Text("Increment") }
// }
// }
//
// fun main() = application {
// Window(onCloseRequest = ::exitApplication) {
// App()
// }
// }