What Is New in Kotlin 1.7
Kotlin 1.7 delivers updates across the language, standard library, and tooling, with a strong focus on stabilizing key features for multi-platform development. The release brings several long-awaited features to a stable state, improving developer experience and code consistency. Here's a summary of the main changes.
| Category | Key Changes |
|---|---|
| Language & Compiler | Stable underscore operator for lambdas, stable exhaustive when statements for sealed and Boolean types, stable type inference changes from Kotlin 1.6. |
| Standard Library | Stable generic one-type parameter replace functions, new memory-efficient random number generator, stable Duration API, new Kotlin-Test framework. |
| Tooling & Gradle | New Kotlin K2 compiler preview for the JVM, new approach for incremental compilation in Gradle, updates to the kapt compiler plugin. |
| Multiplatform | Hierarchical structure support is now the default, enabling shared code to depend on platform-specific implementations directly. |
What language features were stabilized in Kotlin 1.7?
Kotlin 1.7 promotes critical language features to stable, making them safe for production use. The underscore operator for unused lambda parameters helps clarify intent in callbacks. Exhaustive when statements are now stable for sealed and Boolean types, ensuring all cases are handled.
In practice, this means you can use _ for lambda parameters you don't reference, which cleans up code. The compiler will no longer require an else branch in when statements that already cover all possible sealed class subtypes or Boolean values.
// Underscore for unused lambda parameter
list.onEachIndexed { index, _ -> println("Processing index $index") }
// Exhaustive when for Boolean
when (val result = calculate()) {
true -> println("Success")
false -> println("Failure")
// No 'else' needed
}
How does the new random number generator improve performance?
Kotlin 1.7 introduces a new, purely Kotlin-implemented random number generator that is thread-safe and doesn't allocate additional objects. This replaces the previous default which delegated to java.util.Random on the JVM, offering better performance and consistent behavior across all platforms.
You can access it via kotlin.random.Random.Default. This matters because it reduces overhead in loops or concurrent code that frequently generates random values. The new generator produces higher quality random numbers and is now the default for all the random extension functions in the standard library.
// Uses the new, more efficient generator
val randomNumber = Random.nextInt(1, 100)
val randomItem = listOf("a", "b", "c").random()
What changes were made to the standard library APIs?
The standard library received several targeted improvements for common tasks. The replace functions for String and CharArray are now generic and accept a one-type parameter, aligning them with other collection operations. The Duration API is now stable, providing a type-safe way to work with time intervals.
For testing, the new kotlin-test framework version brings more assertions and better multi-platform support. These changes reduce boilerplate and increase code safety, especially when performing string manipulations or measuring time.
// Generic replace function
fun <T> replaceElements(list: List<T>, old: T, new: T): List<T> {
return list.map { if (it == old) new else it }
}
// Using the stable Duration API
val duration = Duration.milliseconds(500)
val result = duration + Duration.seconds(2)
What is the new default for Kotlin Multiplatform projects?
Hierarchical project structure support is now enabled by default for new Kotlin Multiplatform projects. This allows shared code to declare dependencies on platform-specific implementations from other shared source sets, not just common code. It simplifies dependency management and code sharing in complex multi-platform setups.
Before this, you had to opt-in with a flag. This change reflects the maturity of the multi-platform model and makes it easier to build layered architectures where, for example, a shared iOS/Android module can depend on a shared native utility module.
What should developers know about the K2 compiler preview?
Kotlin 1.7 includes an alpha preview of the new K2 compiler for the JVM. This compiler rewrite aims for faster compilation, unified architecture across all platforms, and a foundation for new language features. It's not ready for production but can be enabled with an opt-in compiler flag for experimentation.
This is a long-term investment. In practice, you shouldn't switch your projects to it yet, but it's worth trying on side projects to help the team identify issues. The performance gains and architectural improvements will benefit the entire Kotlin ecosystem once it stabilizes.
FAQ
Is the new underscore operator for lambdas backward compatible?
Yes, it's fully backward compatible. The underscore was already a reserved symbol, so using it as an explicit parameter name doesn't break existing code. It simply provides a clearer intent for unused parameters.
Do I need to migrate my existing random number generation code?
No, migration isn't required. The new random generator is used automatically by the standard library's extension functions. If you were using java.util.Random directly, that will continue to work, but consider switching to kotlin.random.Random for cross-platform consistency.
What happens if I don't update my Gradle build scripts for the new incremental compilation?
The old incremental compilation method is deprecated. While your builds will still work, you might miss out on significant build speed improvements. It's recommended to update the kotlin.incremental.useClasspathSnapshot property in your Gradle settings.
Can I use the stable Duration API in my Android or iOS multiplatform modules?
Absolutely. The Duration API is part of the Kotlin Standard Library and works across all Kotlin targets, including Android, iOS (via Kotlin/Native), JVM, and JS. This is a major advantage for sharing time-related logic.
Why is the K2 compiler still in preview if it's faster?
The K2 compiler is a complete rewrite. While it shows promising speed gains, it needs extensive testing across the vast Kotlin ecosystem to ensure it compiles all existing code correctly and that plugin support (like kapt) is fully functional. Stability is prioritized over early performance gains.