~/dev.log/lang-kotlin

A statically typed language that runs on the JVM (fully interoperable with Java), the default choice for modern Android development and increasingly popular for backend services too.

Setup

kotlinc -version

Most projects use Gradle rather than calling kotlinc directly:

gradle init   # choose Kotlin application
gradle run

Core syntax

fun add(a: Int, b: Int): Int = a + b

fun main() {
    val name = "Ada"   // immutable
    var count = 0      // mutable

    println("Hello, $name! Count: $count")

    val nums = listOf(1, 2, 3)
    val doubled = nums.map { it * 2 }
}

val (immutable reference) vs var (mutable), same immutable-by-default philosophy as Swift and Rust.

Null safety

var maybeName: String? = null // must explicitly opt into nullability

val length = maybeName?.length ?: 0   // safe call + Elvis operator for a default

Like Swift's optionals, the type system distinguishes String (never null) from String? (may be null), the compiler refuses to let a nullable value be used where a non-null one is required without a check first.

Classes and data classes

class Animal(val name: String) {
    fun speak() = "$name makes a sound."
}

// data class, auto-generates equals/hashCode/toString/copy
data class Point(val x: Int, val y: Int)

val p1 = Point(1, 2)
val p2 = p1.copy(y = 5)

When expressions (Kotlin's switch, but an expression)

fun describe(x: Any): String = when (x) {
    is Int -> "an integer: $x"
    is String -> "a string of length ${x.length}"
    else -> "something else"
}

Coroutines (structured concurrency)

import kotlinx.coroutines.*

suspend fun fetchUser(id: Int): String {
    delay(100) // non-blocking "sleep"
    return "User $id"
}

fun main() = runBlocking {
    val user = fetchUser(1)
    println(user)
}

suspend functions are Kotlin's alternative to callback-heavy or thread-heavy async code, they read like synchronous code but don't block the underlying thread.

Purpose Common choice
Android development Jetpack Compose (UI), the modern default over XML layouts
Backend Ktor, Spring Boot (fully supports Kotlin)
Build tool Gradle (Kotlin DSL, build.gradle.kts)
Minecraft plugins Also usable via the same Maven/Gradle + Paper API setup as Java plugins

Common gotchas

  • == in Kotlin checks structural equality by default (calls .equals()), unlike Java where == on objects checks reference identity, use === in Kotlin specifically for reference comparison.
  • Extension functions (adding methods to existing classes, e.g. fun String.shout() = uppercase() + "!") are resolved statically at compile time based on the declared type, not the runtime type, this can surprise people expecting virtual-style dispatch.
  • Platform types from Java interop (no nullability info from Java's type system) can slip past Kotlin's null checks, annotate Java APIs with @Nullable/@NonNull where you control them.