What Is New in Kotlin 1.1 (summary table)
Kotlin 1.1 introduces a mix of stable features, experimental capabilities, and tooling improvements. The key updates are summarized below.
| Category | Key Changes |
|---|---|
| New Language Features | Type aliases, bound callable references, destructuring in lambdas, underscore for unused parameters, sealed and data class inheritance relaxations. |
| JavaScript Target | Full support for targeting JavaScript, enabling code sharing between JVM and browser environments. |
| Coroutines | Introduction of experimental coroutines for asynchronous programming, with several built-in constructs. |
| Standard Library | New extensions for String, numbers, and collections; the takeIf and takeUnless scope functions; also for side effects. |
| Tooling & Compiler | Support for Java 8 bytecode, parameter names in reflection, incremental compilation for Gradle, and IDE improvements. |
| Migration & Compatibility | A compiler flag to ensure binary compatibility with Kotlin 1.0, and migration tools for existing codebases. |
What new language features were added?
Kotlin 1.1 brings several expressive features to the language. Type aliases let you provide alternative names for existing types, which is great for simplifying complex generic signatures.
Bound callable references (this::foo or instance::bar) allow you to reference a method bound to a specific object instance. This makes function composition and passing around method references more flexible.
Refinements to Existing Features
Data classes can now extend other classes, and sealed class subclasses can be defined as top-level declarations in the same file. Destructuring declarations also work in lambda parameters, letting you break apart objects directly.
// Type alias example
typealias FileTable = MutableMap<String, MutableList<File>>
// Destructuring in lambda
map.mapValues { (key, value) -> "$key -> $value" }
// Underscore for unused parameter
foo.forEach { _, value -> println(value) }
How does Kotlin 1.1 handle JavaScript development?
JavaScript is now a fully supported compilation target, not an experimental one. You can write Kotlin code and compile it to run in a browser or Node.js environment.
This opens up code-sharing strategies. You can write common business logic or data models in Kotlin and compile them for both the JVM backend and the JavaScript frontend. The standard library for JavaScript is also more complete and aligned with the JVM version.
In practice, this means you can use the same language idioms and tooling for full-stack development. The interoperability with existing JavaScript modules is handled through external declarations.
What are coroutines and how are they used?
Coroutines are an experimental feature in 1.1 for writing asynchronous, non-blocking code in a more sequential and readable style. They provide a way to suspend computations without blocking threads.
The library includes several builders like launch, async, and runBlocking. These work with suspending functions, marked with the suspend modifier. This model is powerful for tasks like network calls, background processing, or UI event handling.
// Example using `async` coroutine builder
fun main(args: Array<String>) = runBlocking {
val deferredResult: Deferred<Int> = async {
// Simulate a long-running computation
delay(1000L)
42
}
println("Waiting for result...")
println(deferredResult.await())
}
Because they were experimental, using coroutines required an explicit opt-in with a compiler flag. This allowed the team to gather feedback before stabilizing the API.
What improvements were made to the standard library?
The standard library got a significant boost in utility. New extension functions were added for String (like toIntOrNull), numbers, and collections (like minOf/maxOf).
Three new scope functions joined let, apply, run, and with: takeIf, takeUnless, and also. takeIf returns the receiver object if it satisfies a predicate, while also is perfect for performing actions on an object within a call chain.
val input = "Hello"
val output = input.takeIf { it.length > 3 }?.toUpperCase() // "HELLO"
val numbers = mutableListOf(1, 2, 3)
numbers.also { println("Preparing to add") }.add(4)
What tooling and compiler updates should I know about?
The compiler gained the ability to generate Java 8 bytecode, which includes support for default methods in interfaces and lambda expressions in a more efficient form. This matters because it improves interoperability with modern Java libraries.
Gradle builds became faster with the introduction of incremental compilation. The compiler only recompiles classes affected by changes. IDE support improved with better debugging for coroutines and JavaScript, and parameter names are now available via reflection.
A critical addition for teams was the -kotlin-version compatibility flag. Setting this to 1.0 ensures the compiler produces binaries that are usable by code compiled with Kotlin 1.0, smoothing the upgrade path for libraries.
FAQ
Is Kotlin 1.1 source-compatible with 1.0?
Yes, for the most part. Kotlin 1.1 maintains a high degree of source compatibility. However, to ensure your 1.1-compiled libraries can be used by projects still on 1.0, use the -kotlin-version 1.0 compiler flag for binary compatibility.
Are coroutines ready for production use in 1.1?
Coroutines were marked as experimental in Kotlin 1.1. You need to explicitly opt-in with a compiler flag (-Xcoroutines=enable). This signals that their API might change in future releases, so evaluate the stability needs of your project before using them in critical production paths.
Can I use Java 8 features like streams with Kotlin 1.1?
Yes. The Kotlin 1.1 compiler can generate Java 8 bytecode. This allows Kotlin to use Java 8 interface default methods seamlessly and enables more efficient translation of Kotlin lambdas. You still need to configure your build tool (like Gradle or Maven) to target Java 8.
What's the main use case for type aliases?
Type aliases are primarily for improving code readability. They are useful for simplifying long generic type declarations, like complex collection types or function types, giving them a concise and descriptive name without creating a new wrapper class.
How stable is the JavaScript target in 1.1?
The JavaScript target moved from experimental to fully supported in this release. This means it's considered stable for production use, with a complete standard library and robust tooling. You can confidently share Kotlin code between server (JVM) and client (JS) applications.