Skip to content
Kotlin logo

Kotlin

First appeared 2011 (1.0 in 2016) · Andrey Breslav

Java's pragmatic successor — null safety, coroutines and half the boilerplate, on the same JVM.

Overview

Kotlin is a modern, statically typed, cross-platform programming language developed by JetBrains that runs primarily on the Java Virtual Machine (JVM) and is fully interoperable with Java, while also supporting compilation to JavaScript and native code for various platforms. Introduced in 2011 and reaching its first stable release in 2016, Kotlin was designed to be a more concise, expressive, safe, and pragmatic alternative to Java while maintaining 100% interoperability with existing Java code, libraries, and frameworks. Google announced official first-class support for Kotlin on Android at Google I/O 2017, and in 2019 declared it the preferred language for Android app development, cementing its position as a major programming language. Kotlin addresses many of Java's pain points and verbosity while preserving the strengths of the JVM ecosystem. The language features built-in null safety that eliminates the billion-dollar mistake of null pointer exceptions by distinguishing between nullable and non-nullable types at the language level, extension functions that allow adding functionality to existing classes without inheritance, data classes that automatically generate boilerplate code for value objects, sealed classes for representing restricted class hierarchies, coroutines as a first-class language feature for writing asynchronous, non-blocking code in a sequential style, and powerful functional programming capabilities including higher-order functions, lambdas, and immutability support. Kotlin's syntax is clean and concise, often requiring significantly less code than equivalent Java while remaining highly readable. The language supports multiple programming paradigms including object-oriented, functional, and procedural programming, giving developers flexibility in their approach. Kotlin includes smart casts that automatically cast types after null checks or type checks, eliminating redundant casting, operator overloading for creating intuitive APIs, delegation as a first-class language feature, inline functions for performance optimization, and a sophisticated type system with generics, variance annotations, and type inference. The language provides excellent tooling through IntelliJ IDEA and Android Studio, with features like intelligent code completion, refactoring tools, and seamless Java interoperability. Kotlin Multiplatform allows sharing code between different platforms including JVM, Android, iOS, JavaScript, and native applications, enabling developers to write business logic once and use it everywhere while still accessing platform-specific APIs when needed. The language has a comprehensive standard library that extends Java's standard library with useful functions and utilities, making common tasks easier and more expressive. Kotlin is widely used for Android development, server-side applications, web development, desktop applications, and increasingly for multiplatform mobile development. The language has gained rapid adoption in the industry, with major companies migrating their Android apps and backend services to Kotlin, citing improved developer productivity, fewer bugs, and better code maintainability.

Key facts

The reference details, without the paragraph.

First appeared
2011 (1.0 in 2016)
Designed by
JetBrains, led by Andrey Breslav
Typing
Static and strong, with nullability in the type system and pervasive inference
Execution
Compiles to JVM bytecode, JavaScript, or native binaries via LLVM
Memory model
JVM garbage collection on the JVM; reference counting plus cycle collection on Kotlin/Native
Package manager
Gradle (Kotlin DSL) or Maven, backed by Maven Central
File extensions
.kt, .kts
Android status
Google's preferred language for Android since 2019
Interoperability
Fully bidirectional with Java — mix both in one project, file by file
Licence
Apache 2.0

History

How the language got here — the decisions that still shape how you write it.

Kotlin was developed by JetBrains, the Czech software development company best known for creating popular integrated development environments like IntelliJ IDEA, PyCharm, WebStorm, and Android Studio. The project was initiated in July 2010 when JetBrains was looking for a more productive alternative to Java for their own development needs. JetBrains had been using Java for their products but found it increasingly verbose and lacking modern language features that were becoming standard in newer languages. However, they couldn't simply switch to another JVM language like Scala because they needed something that would compile as fast as Java, have excellent IDE support, and be easy for their large team of Java developers to adopt. Finding no existing language that met all their requirements, JetBrains decided to create their own. The language was named after Kotlin Island (Котлин), a small island near St. Petersburg, Russia, where some of the JetBrains team members were located, following the tradition of naming languages after islands (like Java and Ceylon). The project was led by Andrey Breslav, who became the lead language designer, with a team of experienced language developers and compiler engineers. From the beginning, Kotlin was designed with pragmatism in mind: it needed to solve real problems that developers faced daily, compile quickly, integrate seamlessly with existing Java code, and be easy to learn for Java developers. JetBrains open-sourced Kotlin in 2011 under the Apache 2 license, making it freely available and encouraging community participation. The early years of Kotlin development focused on refining the language design, building a robust compiler, and creating excellent tooling support in IntelliJ IDEA. JetBrains used Kotlin internally for their own products, which provided valuable real-world feedback and helped identify issues before the language reached a wider audience. The first stable release, Kotlin 1.0, was announced in February 2016 after years of development and refinement. This release marked Kotlin as production-ready and came with JetBrains' commitment to backward compatibility. The timing was fortuitous, as Android developers were increasingly frustrated with Java's limitations and Oracle's legal disputes with Google over Java APIs. Kotlin offered a modern alternative that worked seamlessly with existing Android development tools and libraries. The language began gaining traction in the Android community, with developers appreciating its conciseness, null safety, and modern features. The turning point came at Google I/O 2017 when Google announced official first-class support for Kotlin on Android, placing it alongside Java as a supported language. This announcement was met with tremendous enthusiasm from the Android developer community, and Kotlin adoption accelerated rapidly. Google's endorsement validated Kotlin's design and gave developers confidence to adopt it for production applications. Major companies including Pinterest, Uber, Netflix, Trello, and Coursera announced they were using Kotlin for their Android apps. In May 2019, at Google I/O, Google went further and announced that Kotlin was now the preferred language for Android app development, with new Android APIs and features being designed with Kotlin in mind. This was a historic moment, as it marked the first time Google had officially preferred a language other than Java for Android. Google also announced that over 50% of professional Android developers were using Kotlin, demonstrating its rapid adoption. JetBrains continued to invest heavily in Kotlin's development, expanding its capabilities beyond the JVM. Kotlin/Native, announced in 2017, allows compiling Kotlin directly to native binaries without a virtual machine, enabling Kotlin to run on iOS, embedded systems, and other platforms. Kotlin/JS enables compiling Kotlin to JavaScript for web development. These efforts culminated in Kotlin Multiplatform, a technology that allows sharing code between different platforms while still accessing platform-specific APIs when needed. This has made Kotlin attractive for companies wanting to share business logic between Android and iOS apps while maintaining native user interfaces. Kotlin has also found success in server-side development, with frameworks like Ktor (created by JetBrains) and Spring Boot providing excellent support for building backend services. The language's coroutines make it particularly well-suited for building scalable, asynchronous server applications. Major companies including Amazon, VMware, and Atlassian use Kotlin for their backend services. The language has evolved steadily with regular releases, adding features like inline classes for performance optimization, contracts for better static analysis, sealed interfaces, context receivers, and continuous improvements to the type system and compiler. Each release has maintained backward compatibility, ensuring that existing code continues to work. Kotlin's success has been remarkable, growing from a JetBrains internal project to one of the most popular programming languages in just over a decade. The language has won numerous awards and consistently ranks high in developer satisfaction surveys. Its success demonstrates that there was indeed room for a better JVM language that could coexist with Java while providing a more modern and productive development experience. JetBrains continues to lead Kotlin's development with input from Google and the broader community, ensuring the language evolves to meet the needs of modern software development while maintaining its core principles of pragmatism, safety, and interoperability.

  1. 2011

    JetBrains announces Kotlin

    The company behind IntelliJ designs a language for its own problem: millions of lines of Java that they wanted to write more concisely without abandoning the JVM. It is named after an island near St Petersburg.

  2. 2016

    Kotlin 1.0

    The first stable release, with a commitment to backwards compatibility. Null safety, data classes, extension functions and smart casts are all present from the start.

  3. 2017

    Google makes it official for Android

    Kotlin becomes a first-class Android language at Google I/O. Adoption is unusually fast because it interoperates with the existing Java codebase rather than replacing it.

  4. 2018

    Coroutines stabilise

    Structured concurrency lands in 1.3: asynchronous code that reads sequentially, with cancellation that propagates correctly through a scope.

  5. 2019

    Kotlin-first on Android

    Google announces that new Android APIs and documentation will target Kotlin first. Java remains supported but is no longer the default path.

  6. 2021

    Kotlin Multiplatform matures

    Shared business logic across Android, iOS, web and desktop, with native UI on each. It targets the layer beneath the UI, which is where most duplicated logic actually lives.

  7. 2024

    The K2 compiler

    Kotlin 2.0 ships a rewritten front end — roughly twice as fast, with better type inference and a cleaner foundation for future language features.

What it is good at

The reasons teams pick it, stated concretely.

  • Null safety in the type system

    `String` and `String?` are different types, and the compiler will not let you dereference the nullable one without handling the null case. This closes the single most common source of runtime crashes on the JVM.

  • Concise without being cryptic

    Data classes, type inference, named and default arguments, and expression bodies typically cut Java code by a third to a half — while staying readable to anyone who knows Java.

  • Coroutines are excellent

    Lightweight, structured concurrency where cancellation propagates automatically through a scope. Launching a hundred thousand coroutines is unremarkable, and the code reads top to bottom.

  • Interoperability that actually works

    Call Java from Kotlin and Kotlin from Java, in the same module, with no wrappers. Migration can be file by file over years, which is why so many large Java codebases adopted it successfully.

  • Extension functions

    Add methods to types you do not own — including `String` and `List` — without inheritance or wrapper classes. Much of Kotlin's standard library is built this way, and it makes domain-specific APIs unusually natural.

Trade-offs

Every language costs you something. Knowing what, before you commit, is the whole point.

  • Build times

    Kotlin compilation is slower than Java's, and Gradle adds its own overhead. The K2 compiler improved this substantially, but a large Android build is still not quick.

  • It is a JVM language, with JVM constraints

    Startup time, memory footprint and the garbage collector all come along. Kotlin/Native exists but has a much smaller ecosystem than the JVM target.

  • Null safety stops at the Java boundary

    Types coming from Java are 'platform types' the compiler cannot verify. Well-annotated libraries help; unannotated ones can still hand you a null the compiler believed was impossible.

  • Coroutines have real depth

    Scopes, dispatchers, `Job` hierarchies, `Flow` and cancellation semantics take genuine study. Misusing `GlobalScope` or swallowing `CancellationException` causes subtle leaks.

  • Smaller talent pool than Java

    Growing quickly, and Java developers learn it fast, but hiring is still a narrower search — outside Android, where the position is reversed.

Code examples

Not syntax tours — the idioms that make code read like the language rather than a translation of another one.

Null safety is enforced, not advised
class User(val name: String, val email: String?)

fun describe(user: User?): String {
    // Safe call plus elvis: no null check ceremony, no possible NPE.
    val name = user?.name ?: "anonymous"

    // Smart cast — after the check, `email` is String, not String?
    val contact = user?.email
    if (contact != null && contact.contains("@")) {
        return "$name <$contact>"
    }
    return name
}

// user!!.name  // the !! operator opts out — and is the one you should avoid
`?.` returns null instead of throwing, `?:` supplies a fallback, and the compiler narrows the type once you have checked. `!!` exists as an escape hatch and is the clearest signal in a code review that something needs rethinking.
Data classes and destructuring
data class Book(
    val title: String,
    val author: String,
    val year: Int = 2026,          // default argument
)

val book = Book(title = "Dune", author = "Herbert", year = 1965)  // named arguments
val reissue = book.copy(year = 2021)                              // copy with changes
val (title, author) = book                                        // destructuring

println(book)            // Book(title=Dune, author=Herbert, year=1965)
println(book == reissue) // false — structural equality, generated for you
One line generates `equals`, `hashCode`, `toString`, `copy` and component functions. Named arguments plus defaults remove the need for builder patterns and overload chains, which is where a lot of Java verbosity came from.
Coroutines with structured concurrency
suspend fun loadDashboard(userId: String): Dashboard = coroutineScope {
    // Both start immediately and run concurrently.
    val profile = async { api.fetchProfile(userId) }
    val orders  = async { api.fetchOrders(userId) }

    Dashboard(profile.await(), orders.await())
}
// If either call fails, the other is cancelled and the exception propagates.
// If the caller's scope is cancelled, both are cancelled too.

viewModelScope.launch {
    val dashboard = withTimeout(5_000) { loadDashboard("u-1") }
    render(dashboard)
}
`coroutineScope` will not return until every child finishes, and cancellation flows both down and up. That is what 'structured' means — you cannot accidentally leave background work running after the thing that wanted it is gone.
Extension functions and scope functions
// Add behaviour to a type you do not own.
fun String.slugify(): String =
    lowercase().replace(Regex("[^a-z0-9]+"), "-").trim('-')

fun List<Book>.byDecade(): Map<Int, List<Book>> =
    groupBy { it.year / 10 * 10 }

// Scope functions keep configuration local and readable.
val request = Request().apply {
    url = "https://api.example.com/books"
    method = "GET"
    timeout = 5_000
}

val slug = "The Left Hand of Darkness".slugify()  // the-left-hand-of-darkness
Extensions are resolved statically — nothing is patched onto the class at runtime — so they are safe and discoverable in the IDE. `apply` returns the receiver after running the block, which replaces the builder pattern for simple configuration.

Common pitfalls

The mistakes that cost everyone an afternoon at least once.

  • Using `!!` to make an error disappear

    It converts a compile-time warning into a runtime crash — precisely the situation Kotlin was designed to prevent. Handle the null, use `?:`, or fix the type.

  • `GlobalScope.launch`

    Work launched there is never cancelled and outlives the component that started it, leaking memory and continuing after a screen closes. Use a scope with a lifecycle: `viewModelScope`, `lifecycleScope`, or your own.

  • Catching `CancellationException`

    A blanket `catch (e: Exception)` inside a coroutine swallows cancellation and keeps the work running. Rethrow it, or catch only the exceptions you mean to handle.

  • Platform types from Java

    A Java method returning `String` becomes `String!` — Kotlin cannot know whether it is nullable. Annotate the Java side, or treat the result as nullable at the boundary.

  • Scope-function soup

    Nesting `let` inside `apply` inside `run` is concise and unreadable. Use them where they clarify, and prefer a named local variable when the chain gets long.

  • Blocking inside a coroutine

    A synchronous JDBC call or `Thread.sleep` on `Dispatchers.Default` starves the pool. Wrap blocking work in `withContext(Dispatchers.IO)`.

In production

Where it is running at scale, and what it is doing there.

  • Google

    Android app development and backend services.

  • Netflix

    Android applications and backend microservices.

  • Uber

    Android mobile applications and backend services.

  • Pinterest

    Android app development and server-side applications.

Learning path

A realistic order to learn things in, with something to build at each step.

  1. 1

    Week 1

    Syntax and null safety

    `val` versus `var`, functions with default and named arguments, nullable types, `when` expressions, and data classes. If you know Java, most of this is a day or two.

    Build this: Convert a small Java class to Kotlin using the IDE's converter, then clean up what it produced by hand.

  2. 2

    Weeks 2–3

    Idiomatic Kotlin

    Collection operations (`map`, `filter`, `groupBy`, `fold`), extension functions, scope functions (`let`, `apply`, `run`, `also`, `with`), sealed classes and destructuring.

    Build this: Rewrite a data-processing task using collection operations instead of loops, and sealed classes instead of enums with fields.

  3. 3

    Weeks 4–6

    Coroutines

    `suspend` functions, `launch` and `async`, dispatchers, `coroutineScope`, cancellation, and `Flow` for streams of values. Understand structured concurrency before writing production code.

    Build this: Fetch from several endpoints concurrently with a timeout and correct cancellation behaviour.

  4. 4

    Months 2–3

    Pick a target

    Android with Jetpack Compose, back end with Ktor or Spring Boot, or Multiplatform for shared logic. Kotlin's shape changes noticeably depending on where you deploy it.

    Build this: Build and ship a small app or service end to end.

  5. 5

    Ongoing

    Deeper ground

    Generics and variance, inline functions and reified types, delegation, DSL construction with lambdas-with-receiver, and the K2 compiler's tooling.

    Build this: Write a small type-safe DSL — a configuration or HTML builder — and see why Kotlin is unusually good at them.

Ecosystem and tooling

The tools you will end up installing whichever project you join.

ToolWhat it does
Gradle (Kotlin DSL)The standard build tool; build scripts are written in Kotlin with full IDE support
Jetpack ComposeDeclarative UI toolkit for Android, and increasingly for desktop and web
KtorKotlin-native, coroutine-first framework for HTTP servers and clients
kotlinx.coroutinesThe coroutine runtime — scopes, dispatchers, channels and Flow
kotlinx.serializationCompile-time-generated JSON and protobuf serialisation with no reflection
Exposed / KtormKotlin SQL frameworks with typed DSLs; JPA and jOOQ also work fine
MockK / KotestMocking and testing designed around Kotlin features such as coroutines and extensions
Kotlin MultiplatformShare business logic across Android, iOS, desktop and web while keeping native UI

Kotlin libraries

28 catalogued, each with installation, worked examples and best practices.

Frequently asked

Should I learn Java before Kotlin?

Not necessarily. Kotlin stands alone as a first JVM language, and Android tutorials assume it. That said, you will read Java — the libraries, the Android framework and most Stack Overflow answers older than a few years are Java — so a reading knowledge is worth having.

Is Kotlin only for Android?

No, though Android is its largest domain. Kotlin is used for back-end services with Ktor and Spring Boot (Spring supports it as a first-class language), for build scripts via the Gradle Kotlin DSL, for data work with Kotlin notebooks, and for shared cross-platform logic.

How does Kotlin compare to Java on performance?

Essentially identical — both compile to JVM bytecode and run on the same JIT. Some Kotlin conveniences allocate slightly more (boxed nullable primitives, lambdas that are not inlined), and `inline` functions can be faster than the Java equivalent. In practice the difference is noise next to your algorithm and I/O.

Are coroutines the same as threads?

No. A coroutine is a suspendable computation that runs on a thread from a pool and releases it while waiting. That is why a hundred thousand coroutines is reasonable and a hundred thousand threads is not. The mental model is closer to `async`/`await` than to `Thread`.

Is Kotlin Multiplatform ready for production?

For sharing non-UI logic — networking, persistence, validation, business rules — yes, and several large apps ship it. Sharing UI via Compose Multiplatform is more mature on desktop and Android than on iOS and web. The usual recommendation is to share the layer beneath the UI and keep the UI native.

Will Kotlin replace Java?

Unlikely, and it does not need to. They run on the same platform and interoperate freely, so most organisations run both — new modules in Kotlin, existing ones in Java. Java has also absorbed several of the ideas Kotlin popularised, such as records and pattern matching.