Kotlin for Java Programmers

Last update: 2023-06-24 05:18:44 +0800 +0800
tags: Kotlin | Java | Jvm
Available translations: 日本語 / 中文(简体) / 中文(繁體)

Kotlin compiles to JVM bytecode and interoperates directly with Java, while adding null safety, concise declarations, extension functions, and structured concurrency.

Classes and Constructors #

A class has one primary constructor in its header and may have secondary constructors in its body. Primary-constructor parameters become properties only when marked val or var; initialization code belongs in an init block.

kotlin
class Account(val id: String, initialBalance: Int) {
    var balance = initialBalance
        private set

    init {
        require(initialBalance >= 0)
    }

    constructor(id: String) : this(id, 0)
}

Secondary constructors must delegate to the primary constructor, directly or through another secondary constructor. Prefer the primary constructor plus default parameters when that expresses the API clearly.

Extensions and Nullability #

An extension function looks like an instance method at the call site, but it is resolved statically; it cannot truly override a member method.

kotlin
fun String.initials(): String =
    trim().split(Regex("\\s+")).joinToString("") { it.take(1) }

Kotlin distinguishes String from nullable String?. Use safe calls (?.), the Elvis operator (?:), and explicit checks rather than Java-style nullability assumptions. Avoid !! except where failure is genuinely the right contract.

Coroutines #

suspend fun marks a function that may suspend without blocking its thread. The low-level kotlin.coroutines package defines primitives such as CoroutineContext and Continuation; the kotlinx.coroutines library provides practical APIs and must be added separately.

kotlin
class UserService(private val api: UserApi) {
    suspend fun load(id: String): User = api.fetch(id)
}

Launch work from a structured CoroutineScope, not GlobalScope. A Job represents cancellable work, and a CoroutineDispatcher selects execution threads; common dispatchers include Dispatchers.Default and Dispatchers.IO. Cancellation is cooperative, so suspending calls and loops should not swallow CancellationException.

Use CoroutineExceptionHandler for reporting uncaught exceptions from root coroutines, not as ordinary error handling. Child failures and cancellation follow structured-concurrency rules, which makes lifetimes explicit.

Comments

Read or comment on GitHub (sign-in required to comment)