What Is New in Kotlin 1.2
Kotlin 1.2 brings key enhancements focused on code reuse across platforms and core language refinements. The headline feature is experimental support for sharing code between JVM and JavaScript targets.
| Category | Key Changes |
|---|---|
| New Feature | Multiplatform projects (experimental) |
| Language & Library | Array literals in annotations, lateinit top-level/properties, inline enum values, improved smart cast handling |
| Compiler | Support for compiling against Java 9 bytecode, -Xjava-parameters flag, incremental compilation for Gradle |
| JavaScript | TypedArrays support, better DCE and file generation |
How does Kotlin 1.2 enable code sharing?
The main answer is experimental multiplatform projects. This lets you write common modules containing code shared between JVM and JavaScript backends, with expected declarations to access platform-specific APIs.
In practice, you define a common module and then platform-specific modules (like JVM or JS) that implement the expected declarations. This matters because it reduces duplication for logic that should be identical on both the server and the client.
// Common module
expect fun currentTime(): Long
// JVM module
actual fun currentTime(): Long = System.currentTimeMillis()
// JS module
actual fun currentTime(): Long = Date().getTime().toLong()
What language improvements were added?
Kotlin 1.2 smoothed out several rough edges in the language. You can now use array literals (["a", "b"]) in annotations, which is more concise than the old arrayOf syntax.
Lateinit and Enums
The lateinit modifier can be used on top-level properties and local variables, not just class members. This is useful for dependency injection setups. For enums, you can access the enumValues<T>() and enumValueOf<T>() functions inline.
Smarter Smart Casts
The compiler got better at smart casts when a variable is checked for null in a lambda. This fixes a common pain point where you had to re-check nullability manually.
How did the compiler improve?
Compilation got faster and more compatible with newer Java versions. The compiler can now generate Java 9 bytecode with the module system (-jvm-target 1.9 flag).
For Gradle builds, incremental compilation is now supported for changes in dependent non-Kotlin modules. The -Xjava-parameters flag tells the compiler to preserve Java method parameter names for better Spring and Jackson interoperability.
What changed for Kotlin/JS development?
The JavaScript backend gained better interoperability and optimization. It now provides support for TypedArrays, which allows efficient handling of binary data when interacting with JS libraries.
Dead code elimination (DCE) works more reliably. You also have more control over the generated JS file names and directories through the outputFile and sourceMapEmbedSources options in the Gradle plugin.
FAQ
Is the multiplatform feature stable?
No, it's marked as experimental in Kotlin 1.2. The API and tooling might change in future versions based on feedback, so be prepared for adjustments if you adopt it early.
Can I use array literals anywhere now?
No, they are specifically enabled for annotation arguments. You still use arrayOf(...) for regular array creation in other parts of your code.
Why does the -Xjava-parameters flag matter?
It preserves parameter names in Java bytecode. This is crucial for frameworks like Spring that use parameter name reflection for annotation-based mapping, preventing you from needing the -parameters javac flag separately.
Does incremental compilation work with Android?
The release notes specifically mention support for Gradle for changes in dependent non-Kotlin modules. While beneficial for multi-module projects, always test with your specific Android Gradle plugin version as compatibility can vary.
What's the main use case for lateinit on a local variable?
It's a niche but useful case for variables initialized by a dependency injection framework within a function scope, or for variables set in a lambda that is guaranteed to run before use.