Kotlin 1.4-M3 is Out: Standard Library Changes
source link: https://blog.jetbrains.com/kotlin/2020/07/kotlin-1-4-m3-is-out-standard-library-changes/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Today we’re glad to present the last milestone preview of Kotlin 1.4 – 1.4-M3 . In this post, we’ll guide you through the changes this preview brings to the Kotlin standard library. Other components are also getting updates in M3; we’ll cover them soon in another blog post with the release candidate version (1.4-RC), which will finalize the scope of Kotlin 1.4.
The standard library changes in 1.4-M3 include:
-
JVM libraries now come with the
module-info
descriptor - Functional interfaces are added to the standard library
- New collection operations to cover real-life cases
-
@Throws
annotation in the common library - Deprecation of some functions on floating-point arrays
You can find the complete list of changes in the change log . As always, we’re really grateful to our external contributors .
We would appreciate it very much if you couldtry the preview andshare your feedback.
Standard library artifacts now include module-info descriptors
Starting from Java 9, you can modularize your application thanks to the Jigsaw project. The
jlink
tool
allows you to generate a custom Java runtime image containing only the platform modules that are required for your app. You could use jlink
with Kotlin standard library artifacts before, but you had to use separate artifacts for that – the ones with the “modular” classifier – and the whole setup wasn’t straightforward. The inability to include module descriptors in main artifacts was caused by issues with Android tooling, which have now been fixed.
Kotlin 1.4 adds module-info.java
module information to default standard library artifacts, so you can use them with jlink
with ease. In Android, make sure you use the Android Gradle plugin version 3.2 or higher, which can correctly process jars with module-info.
fun interfaces in the standard library
Kotlin 1.4 supports SAM conversions for Kotlin classes
. You can mark an interface with only a single abstract method as a fun interface
, and then pass a lambda as an argument when that interface is expected as a parameter. In the standard library, the following interfaces are now declared as fun interface
‘s:
-
Comparator
-
ReadOnlyProperty
-
PropertyDelegateProvider
(was introduced in1.4-M2)
You can use a SAM-constructor that takes a lambda as a parameter to create an instance. The resulting code becomes much simpler:
Collection operations
-
A new
sumOf
function takes a selector function and returns a sum of its values on all elements of a collection. It is pretty similar to the existingsumBy
andsumByDouble
functions. The key difference is that the newsumOf
function takes selectors with various return types, thus letting you handle sums of different types in the same way. Namely, sumOf produces sums of the typesInt
,Long
,Double
,UInt
,ULong
. On the JVM,BigInteger
andBigDecimal
are also available.data class OrderItem(val name: String, val price: Double, val count: Int) fun main() { //sampleStart val order = listOf<OrderItem>( OrderItem("Cake", price = 10.0, count = 1), OrderItem("Coffee", price = 2.5, count = 3), OrderItem("Tea", price = 1.5, count = 2)) val total = order.sumOf { it.price * it.count} // Double val count = order.sumOf { it.count } // Int //sampleEnd println("You've ordered $count items that cost $total in total") }
-
The
min
andmax
functions have been renamed tominOrNull
andmaxOrNull
. Since their introduction in 1.0,min
andmax
have returnednull
on empty collections. This contradicts the naming convention used across the Kotlin collections API: functions without the*OrNull
suffix throw an exception if the receiver collection is empty. To get anull
instead, you should use the*OrNull
version of the function, for example,firstOrNull
.
Thus, we decided to gradually change the behavior ofmin
andmax
. In 1.4-M3, we’re addingminOrNull
andmaxOrNull
as synonyms formin
andmax
and starting the deprecation cycle formin
andmax
to reintroduce them with non-null return types. -
We’ve introduced
minOf
andmaxOf
functions that return the minimum or the maximum value of the given selector function on the collection items. These functions cover the missing case for which it was required to writemap { selector }.max()!!
ormaxBy { selector }!!.selector
(ormin
andminBy
).data class OrderItem(val name: String, val price: Double, val count: Int) fun main() { //sampleStart val order = listOf<OrderItem>( OrderItem("Cake", price = 10.0, count = 1), OrderItem("Coffee", price = 2.5, count = 3), OrderItem("Tea", price = 1.5, count = 2)) val highestPrice = order.maxOf { it.price } //sampleEnd println("The most expensive item in the order costs $highestPrice") }
For consistency with the existing API, we also added
minOfWith
andmaxOfWith
, which take aComparator
as an argument.All four new functions follow the non-null convention we described above: they throw exceptions on empty collections and have
*orNull
versions that returnnull
in this case. -
New overloads for
flatMap
andflatMapTo
let you use transformations with return types that don’t match the receiver type, namely:-
transformations to
Sequence
onIterable
,Array
, andMap
-
transformations to
Iterable
onSequence
fun main() { //sampleStart val list = listOf("kot", "lin") val lettersList = list.flatMap { it.asSequence() } val lettersSeq = list.asSequence().flatMap { it.toList() } //sampleEnd println(lettersList) println(lettersSeq.toList()) }
-
transformations to
-
A new
flatMapIndexed
function has been added as a counterpart forflatMap
. As you may already know,Indexed
in the name of a collection-processing function means that the operation applied has the element index as a parameter.fun main() { //sampleStart val list = listOf("hello", "kot", "lin", "world") val kotlin = list.flatMapIndexed { index, item -> if (index in 1..2) item.toList() else emptyList() } //sampleEnd println(kotlin) }
Common @Throws annotation
Although Kotlin doesn’t have checked exceptions
, it uses the
@Throws
annotation
for interoperability with languages that do have them, such as Java and Swift. Previously, there were separate annotations with this name for JVM ( kotlin.jvm.Throws
) and Native ( kotlin.native.Throws
). Starting from 1.4-M3, the @Throws
annotation is available as a part of the common library directly in the kotlin
package ( kotlin.Throws)
, which allows you to use it in the common code.
@Throws in suspending functions in Swift and Objective-C
In 1.4-M1, we announced changes in exception handling in Objective-C/Swift interop
: now NSError
is thrown only for exceptions that are instances of classes specified as parameters of @Throws
annotation (or their subclasses). In 1.4-M2, we introduced basic support for Kotlin’s suspending functions in Swift and Objective-C
. In 1.4-M3, there are small changes in the behavior of suspending functions annotated with @Throws
:
-
If you have a
suspend fun
annotated with@Throws
, you need to specifyCancellationException::class
as a parameter of the@Throws
annotation. Otherwise, you will get a compilation error. -
If there is no
@Throws
annotation on asuspend fun
, it will implicitly use@Throws(CancellationException::class)
when you call it from Swift.
Equality in floating-point arrays
Many of you know these handy extension functions for container types – contains
, indexOf
, and lastIndexOf
. Some time ago, we figured out that their behavior on floating-point arrays ( FloatArray
and DoubleArray
) may be controversial and can seem incorrect.
To be more specific, they use the IEEE 754 standard for floating-point arithmetics. This standard defines the following equality rules for corner cases:
-
NaN
is not equal toNaN
-
-0.0
is equal to0.0
Such rules may lead to unexpected results, for example:
fun main() { //sampleStart val darray = doubleArrayOf(Double.NaN, 0.0) println (darray.contains(darray[0])) // false! //sampleEnd }
Additionally, such behavior is inconsistent with how the same functions work on lists, because they use the total order equality:
fun main() { //sampleStart val listOfDouble: List<Double> = listOf(0.0, Double.NaN) val listFromArray: List<Double> = doubleArrayOf(0.0, Double.NaN).asList() println(listOfDouble.contains(Double.NaN)) // true println(listFromArray.contains(Double.NaN)) // false in previous versions //sampleEnd }
In 1.4-M3, we start the deprecation cycle for the contains
, indexOf
, and lastIndexOf
extension functions of FloatArray
and DoubleArray
. When trying to use them, you will see warnings with instructions for replacing the usages of these functions.
In future releases, we’ll tighten the deprecation level to ERROR
and remove these functions from the public API.
Converting from KType to Java Type
In Kotlin 1.3.40, we
added a useful typeOf
function
to the standard library. This function returns a runtime representation of the given reified type T
as an instance of
KType
. However, in many practical use cases, you need to work with the Java reflection
java.lang.reflect.Type
objects rather than with KType
s. It was already possible to perform the necessary conversion, but this required using the full kotlin-reflect
dependency. Now we’ve updated the standard library with a way to convert KType
to Java Type
– a KType.javaType
extension property that returns Java Type
:
import kotlin.reflect.javaType import kotlin.reflect.typeOf @OptIn(ExperimentalStdlibApi::class) inline fun <reified T> accessReifiedTypeArg() { val kType = typeOf<T>() println("Kotlin type: $kType") println("Java type: ${kType.javaType}") } @OptIn(ExperimentalStdlibApi::class) fun main() { accessReifiedTypeArg<String>() // Kotlin type: kotlin.String // Java type: class java.lang.String accessReifiedTypeArg<List<String>>() // Kotlin type: kotlin.collections.List<kotlin.String> // Java type: java.util.List<java.lang.String> }
Note that so far the obtained Java Type
doesn’t behave correctly in some corner cases (like annotated type parameters or declaration-site variance), so KType.javaType
stays experimental. You can find more details about the unsupported cases in thisissue.
Compatibility
Note that Kotlin 1.4 is not backward-compatible with 1.3 in some corner cases. All such cases were carefully reviewed by the language committee and will be listed in the “compatibility guide” (similar to this one ). For now, you can find this list inYouTrack.
Pre-release notes
Note that the backward compatibility guarantees do not cover pre-release versions. The features and the API can change in subsequent releases. When we reach a final RC, all binaries produced by pre-release versions will be outlawed by the compiler, and you will be required to recompile everything that was compiled by 1.4‑Mx.
How to try the latest features
As always, you can try Kotlin online at play.kotl.in .
In IntelliJ IDEA and Android Studio , you can update the Kotlin Plugin to version 1.4-M3. See how to do this .
If you want to work on existing projects that were created before installing the preview version, you need to configure your build for the preview version in Gradle or Maven .
You can download the command-line compiler from the Github release page .
You can use the following versions of the libraries published together with this release:
- kotlinx.atomicfu version: 0.14.3-1.4-M3
- kotlinx.coroutines version: 1.3.7-1.4-M3
- kotlinx.serialization version: 0.20.0-1.4-M3
- ktor version: 1.3.2-1.4-M3
The release details and the list of compatible libraries are also available here .
Share your feedback
We’re grateful for all your bug reports in ourissue tracker, and we’ll do our best to fix all the most important issues before the final release.
You are also welcome to join the #eap channel in our Kotlin Slack (get an invite here ). In this channel, you can ask questions, participate in discussions, and get notifications of new preview builds.
Let’s Kotlin!
External contributions
We’d like to thank all of our external contributors whose pull requests were included in this release:
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK