What's new in Kotlin 1.2
Release date: 28 November 2017
Table of contents
Multiplatform projects (experimental)
A common module contains code that is not specific to any platform, as well as declarations without implementation of platform-dependent APIs.
A platform module contains implementations of platform-dependent declarations in the common module for a specific platform, as well as other platform-dependent code.
A regular module targets a specific platform and can either be a dependency of platform modules or depend on platform modules.
When you compile a multiplatform project for a specific platform, the code for both the common and platform-specific parts is generated.
A key feature of the multiplatform project support is the possibility to express dependencies of common code on platform-specific parts through expected and actual declarations. An expected declaration specifies an API (class, interface, annotation, top-level declaration etc.). An actual declaration is either a platform-dependent implementation of the API or a typealias referring to an existing implementation of the API in an external library. Here's an example:
In the common code:
In the JVM platform code:
See the multiplatform programming documentation for details and steps to build a multiplatform project.
Other language features
Array literals in annotations
Starting with Kotlin 1.2, array arguments for annotations can be passed with the new array literal syntax instead of the
The array literal syntax is constrained to annotation arguments.
Lateinit top-level properties and local variables
lateinit modifier can now be used on top-level properties and local variables. The latter can be used, for example, when a lambda passed as a constructor argument to one object refers to another object which has to be defined later:
Check whether a lateinit var is initialized
You can now check whether a lateinit var has been initialized using
isInitialized on the property reference:
Inline functions with default functional parameters
Inline functions are now allowed to have default values for their inlined functional parameters:
Information from explicit casts is used for type inference
The Kotlin compiler can now use information from type casts in type inference. If you’re calling a generic method that returns a type parameter
T and casting the return value to a specific type
Foo, the compiler now understands that
T for this call needs to be bound to the type
This is particularly important for Android developers, since the compiler can now correctly analyze generic
findViewById calls in Android API level 26:
Smart cast improvements
When a variable is assigned from a safe call expression and checked for null, the smart cast is now applied to the safe call receiver as well:
Also, smart casts in a lambda are now allowed for local variables that are only modified before the lambda:
Support for ::foo as a shorthand for this::foo
A bound callable reference to a member of
this can now be written without explicit receiver,
::foo instead of
this::foo. This also makes callable references more convenient to use in lambdas where you refer to a member of the outer receiver.
Breaking change: sound smart casts after try blocks
Earlier, Kotlin used assignments made inside a
try block for smart casts after the block, which could break type- and null-safety and lead to runtime failures. This release fixes this issue, making the smart casts more strict, but breaking some code that relied on such smart casts.
To switch to the old smart casts behavior, pass the fallback flag
-Xlegacy-smart-cast-after-try as the compiler argument. It will become deprecated in Kotlin 1.3.
Deprecation: data classes overriding copy
When a data class derived from a type that already had the
copy function with the same signature, the
copy implementation generated for the data class used the defaults from the supertype, leading to counter-intuitive behavior, or failed at runtime if there were no default parameters in the supertype.
Inheritance that leads to a
copy conflict has become deprecated with a warning in Kotlin 1.2 and will be an error in Kotlin 1.3.
Deprecation: nested types in enum entries
Inside enum entries, defining a nested type that is not an
inner class has been deprecated due to issues in the initialization logic. This causes a warning in Kotlin 1.2 and will become an error in Kotlin 1.3.
Deprecation: single named argument for vararg
For consistency with array literals in annotations, passing a single item for a vararg parameter in the named form (
foo(items = i)) has been deprecated. Please use the spread operator with the corresponding array factory functions:
There is an optimization that removes redundant arrays creation in such cases, which prevents performance degradation. The single-argument form produces warnings in Kotlin 1.2 and is to be dropped in Kotlin 1.3.
Deprecation: inner classes of generic classes extending Throwable
Inner classes of generic types that inherit from
Throwable could violate type-safety in a throw-catch scenario and thus have been deprecated, with a warning in Kotlin 1.2 and an error in Kotlin 1.3.
Deprecation: mutating backing field of a read-only property
Mutating the backing field of a read-only property by assigning
field = ... in the custom getter has been deprecated, with a warning in Kotlin 1.2 and an error in Kotlin 1.3.
Kotlin standard library artifacts and split packages
The Kotlin standard library is now fully compatible with the Java 9 module system, which forbids split packages (multiple jar files declaring classes in the same package). In order to support that, new artifacts
kotlin-stdlib-jdk8 are introduced, which replace the old
The declarations in the new artifacts are visible under the same package names from the Kotlin point of view, but have different package names for Java. Therefore, switching to the new artifacts will not require any changes to your source code.
Another change made to ensure compatibility with the new module system is removing the deprecated declarations in the
kotlin.reflect package from the
kotlin-reflect library. If you were using them, you need to switch to using the declarations in the
kotlin.reflect.full package, which is supported since Kotlin 1.1.
windowed, chunked, zipWithNext
New extensions for
CharSequence cover such use cases as buffering or batch processing (
chunked), sliding window and computing sliding average (
windowed) , and processing pairs of subsequent items (
fill, replaceAll, shuffle/shuffled
A set of extension functions was added for manipulating lists:
shuffled for read-only
Math operations in kotlin-stdlib
Satisfying the longstanding request, Kotlin 1.2 adds the
kotlin.math API for math operations that is common for JVM and JS and contains the following:
tanand inverse of them:
tanhand their inverse:
pow(an extension function),
round(half to even) functions
roundToLong(half to integer) extension functions
- Sign and absolute value:
minof two values
- Binary representation:
Double.fromBits(these are in the
The same set of functions (but without constants) is also available for
Operators and conversions for BigInteger and BigDecimal
Kotlin 1.2 introduces a set of functions for operating with
BigDecimal and creating them from other numeric types. These are:
- Arithmetic and bitwise operator functions:
%and infix functions
--, and a function
Floating point to bits conversions
New functions were added for converting
Float to and from their bit representations:
Float.fromBitsfor creating floating point numbers from the bit representation
Regex is now serializable
kotlin.text.Regex class has become
Serializable and can now be used in serializable hierarchies.
Closeable.use calls Throwable.addSuppressed if available
Closeable.use function calls
Throwable.addSuppressed when an exception is thrown during closing the resource after some other exception.
To enable this behavior you need to have
kotlin-stdlib-jdk7 in your dependencies.
Constructor calls normalization
Ever since version 1.0, Kotlin supported expressions with complex control flow, such as try-catch expressions and inline function calls. Such code is valid according to the Java Virtual Machine specification. Unfortunately, some bytecode processing tools do not handle such code quite well when such expressions are present in the arguments of constructor calls.
To mitigate this problem for the users of such bytecode processing tools, we’ve added a command-line compiler option (
-Xnormalize-constructor-calls=MODE) that tells the compiler to generate more Java-like bytecode for such constructs. Here
MODE is one of:
disable(default) – generate bytecode in the same way as in Kotlin 1.0 and 1.1.
enable– generate Java-like bytecode for constructor calls. This can change the order in which the classes are loaded and initialized.
preserve-class-initialization– generate Java-like bytecode for constructor calls, ensuring that the class initialization order is preserved. This can affect overall performance of your application; use it only if you have some complex state shared between multiple classes and updated on class initialization.
The “manual” workaround is to store the values of sub-expressions with control flow in variables, instead of evaluating them directly inside the call arguments. It’s similar to
Java-default method calls
Before Kotlin 1.2, interface members overriding Java-default methods while targeting JVM 1.6 produced a warning on super calls:
Super calls to Java default methods are deprecated in JVM target 1.6. Recompile with '-jvm-target 1.8'. In Kotlin 1.2, there's an error instead, thus requiring any such code to be compiled with JVM target 1.8.
Breaking change: consistent behavior of x.equals(null) for platform types
x.equals(null) on a platform type that is mapped to a Java primitive (
Char!) incorrectly returned
x was null. Starting with Kotlin 1.2, calling
x.equals(...) on a null value of a platform type throws an NPE (but
x == ... does not).
To return to the pre-1.2 behavior, pass the flag
-Xno-exception-on-explicit-equals-for-boxed-null to the compiler.
Breaking change: fix for platform null escaping through an inlined extension receiver
Inline extension functions that were called on a null value of a platform type did not check the receiver for null and would thus allow null to escape into the other code. Kotlin 1.2 forces this check at the call sites, throwing an exception if the receiver is null.
To switch to the old behavior, pass the fallback flag
-Xno-receiver-assertions to the compiler.
TypedArrays support enabled by default
The JS typed arrays support that translates Kotlin primitive arrays, such as
Warnings as errors
The compiler now provides an option to treat all warnings as errors. Use
-Werror on the command line, or the following Gradle snippet: