Что нового в Kotlin 1.4.30
В Kotlin 1.4.30 представлены предварительные версии новых языковых возможностей, новая IR-архитектура бэкенда компилятора Kotlin/JVM получила статус бета-версии, а также были внесены различные улучшения производительности и функциональности.
Подробнее о новых возможностях можно узнать из этой записи в блоге.
Языковые возможности
В Kotlin 1.5.0 появятся новые языковые возможности: поддержка JVM-записей, sealed-интерфейсы и стабильные inline-классы. В Kotlin 1.4.30 вы можете попробовать эти возможности и улучшения в предварительном режиме. Будем очень признательны, если вы поделитесь с нами отзывами в соответствующих задачах YouTrack: это позволит нам учесть их до выпуска 1.5.0.
Чтобы включить эти языковые возможности и улучшения в предварительном режиме, необходимо добавить определенные параметры компилятора. Подробности см. в разделах ниже.
Подробнее о предварительной версии новых возможностей можно узнать из этой записи в блоге.
Поддержка JVM-записей
Выпуск JDK 16 предполагает стабилизацию нового типа классов Java под названием record. Чтобы предоставить все преимущества Kotlin и сохранить совместимость с Java, Kotlin вводит экспериментальную поддержку классов-записей.
Классы-записи, объявленные в Java, можно использовать в Kotlin так же, как классы со свойствами. Дополнительные действия не требуются.
Начиная с версии 1.4.30, можно объявить класс-запись в Kotlin, используя аннотацию @JvmRecord для класса данных:
@JvmRecord data class User(val name: String, val age: Int)
Чтобы попробовать предварительную версию JVM-записей, добавьте параметры компилятора -Xjvm-enable-preview и -language-version 1.5.
Мы продолжаем работу над поддержкой JVM-записей и будем очень признательны, если вы поделитесь с нами отзывами в этой задаче YouTrack.
Подробнее о реализации, ограничениях и синтаксисе см. в KEEP.
Sealed-интерфейсы
В Kotlin 1.4.30 мы представляем прототип sealed-интерфейсов. Они дополняют sealed-классы и позволяют создавать более гибкие ограниченные иерархии классов.
Они могут выступать в роли «внутренних» интерфейсов, которые нельзя реализовать за пределами того же модуля. Например, это позволяет полагаться на данный факт при написании исчерпывающих выражений when.
sealed interface Polygon
class Rectangle(): Polygon
class Triangle(): Polygon
// when() is exhaustive: no other polygon implementations can appear
// after the module is compiled
fun draw(polygon: Polygon) = when (polygon) {
is Rectangle -> // ...
is Triangle -> // ...
}
Еще один вариант использования: с sealed-интерфейсами можно наследовать класс от двух или более sealed-суперклассов.
sealed interface Fillable {
fun fill()
}
sealed interface Polygon {
val vertices: List<Point>
}
class Rectangle(override val vertices: List<Point>): Fillable, Polygon {
override fun fill() { /*...*/ }
}
Чтобы попробовать предварительную версию sealed-интерфейсов, добавьте параметр компилятора -language-version 1.5. После этого вы сможете использовать модификатор sealed для интерфейсов. Будем очень признательны, если вы поделитесь с нами отзывами в этой задаче YouTrack.
Иерархии sealed-классов в пределах пакета
Теперь sealed-классы могут образовывать более гибкие иерархии. Их подклассы могут находиться во всех файлах одной единицы компиляции и одного пакета. Ранее все подклассы должны были находиться в одном файле.
Прямые подклассы могут быть верхнеуровневыми или вложенными в любое количество других именованных классов, именованных интерфейсов или именованных объектов. Подклассы sealed-класса должны иметь полностью квалифицированное имя — они не могут быть локальными или анонимными объектами.
Чтобы попробовать иерархии sealed-классов в пределах пакета, добавьте параметр компилятора -language-version 1.5. Будем очень признательны, если вы поделитесь с нами отзывами в этой задаче YouTrack.
Улучшенные inline-классы
В Kotlin 1.4.30 inline-классы получили статус бета-версии, а также следующие возможности и улучшения:
-
Поскольку inline-классы основаны на значениях, их можно объявлять с помощью модификатора
value. Модификаторыinlineиvalueтеперь эквивалентны. В будущих версиях Kotlin мы планируем объявить модификаторinlineустаревшим.Теперь для бэкенда JVM перед объявлением класса Kotlin требует аннотацию
@JvmInline:inline class Name(private val s: String) value class Name(private val s: String) // For JVM backends @JvmInline value class Name(private val s: String)
-
В inline-классах могут быть блоки
init. В них можно добавить код, который будет выполнен сразу после создания экземпляра класса:@JvmInline value class Negative(val x: Int) { init { require(x < 0) { } } } -
Вызов функций с inline-классами из кода Java: до Kotlin 1.4.30 из-за модификации имен вы не могли вызывать из Java функции, принимающие inline-классы. Теперь модификацию имен можно отключить вручную. Чтобы вызывать такие функции из кода Java, добавьте аннотацию
@JvmNameперед объявлением функции:inline class UInt(val x: Int) fun compute(x: Int) { } @JvmName("computeUInt") fun compute(x: UInt) { } -
В этом выпуске мы изменили схему модификации имен функций, чтобы исправить некорректное поведение. Эти изменения привели к изменениям ABI.
Начиная с версии 1.4.30 компилятор Kotlin по умолчанию использует новую схему модификации имен. Используйте флаг компилятора
-Xuse-14-inline-classes-mangling-scheme, чтобы заставить компилятор использовать старую схему модификации имен из версии 1.4.0 и сохранить двоичную совместимость.
В Kotlin 1.4.30 inline-классы получили статус бета-версии, и в будущих выпусках мы планируем присвоить им статус стабильных. Будем очень признательны, если вы поделитесь с нами отзывами в этой задаче YouTrack.
Чтобы попробовать предварительную версию inline-классов, добавьте параметр компилятора -Xinline-classes или -language-version 1.5.
Подробнее об алгоритме модификации имен см. в KEEP.
Kotlin/JVM
IR-бэкенд компилятора JVM получил статус бета-версии
Бэкенд компилятора на основе IR для Kotlin/JVM, представленный в версии 1.4.0 в статусе альфа-версии, получил статус бета-версии. Это последний этап перед стабилизацией, после которого IR-бэкенд станет используемым по умолчанию для компилятора Kotlin/JVM.
Теперь снято ограничение на использование бинарных файлов, созданных IR-компилятором. Ранее код, скомпилированный новым бэкендом JVM IR, можно было использовать только при включенном новом бэкенде. Начиная с версии 1.4.30 такого ограничения нет, поэтому новый бэкенд можно использовать для сборки компонентов для сторонних пользователей, например библиотек. Попробуйте бета-версию нового бэкенда и поделитесь отзывами в нашем трекере задач.
Чтобы включить новый бэкенд JVM IR, добавьте следующие строки в файл конфигурации проекта:
-
В Gradle:
tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile::class) { kotlinOptions.useIR = true }tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile) { kotlinOptions.useIR = true } -
В Maven:
<configuration> <args> <arg>-Xuse-ir</arg> </args> </configuration>
Подробнее об изменениях, привнесенных бэкендом JVM IR, читайте в этой записи в блоге.
Kotlin/Native
Повышение производительности
В Kotlin/Native в версии 1.4.30 внесено множество улучшений производительности, благодаря которым сократилось время компиляции. Например, время, необходимое для повторной сборки фреймворка в примере «Сетевое взаимодействие и хранение данных с Kotlin Multiplatform Mobile», сократилось с 9,5 секунды (в версии 1.4.10) до 4,5 секунды (в версии 1.4.30).
Целевая платформа 64-разрядного симулятора Apple watchOS
Целевая платформа симулятора x86 устарела для watchOS начиная с версии 7.0. Чтобы поддерживать последние версии watchOS, в Kotlin/Native появилась новая целевая платформа watchosX64 для запуска симулятора на 64-разрядной архитектуре.
Поддержка библиотек Xcode 12.2
Мы добавили поддержку новых библиотек, поставляемых с Xcode 12.2. Теперь их можно использовать в коде Kotlin.
Kotlin/JS
Ленивая инициализация свойств верхнего уровня
Для IR-бэкенда Kotlin/JS реализован прототип ленивой инициализации свойств верхнего уровня. Это уменьшает необходимость инициализировать все свойства верхнего уровня при запуске приложения и должно значительно сократить время запуска.
Мы продолжим работу над ленивой инициализацией и просим вас попробовать текущий прототип и поделиться своими мнениями и результатами в этой задаче YouTrack или в канале #javascript официального Slack-сообщества Kotlin (получить приглашение можно здесь).
Чтобы использовать ленивую инициализацию, добавьте параметр компилятора -Xir-property-lazy-initialization при компиляции кода компилятором JS IR.
Улучшения проектов Gradle
Поддержка кэша конфигурации Gradle
Начиная с версии 1.4.30 плагин Kotlin Gradle поддерживает функцию кэша конфигурации. Она ускоряет процесс сборки: после запуска команды Gradle выполняет этап конфигурации и вычисляет граф задач. Gradle сохраняет результат в кэше и использует его при последующих сборках.
Чтобы начать использовать эту возможность, можно воспользоваться командой Gradle или настроить IDE на основе IntelliJ.
Стандартная библиотека
API преобразования текста в верхний и нижний регистр без учета локали
В этом выпуске представлен экспериментальный API, не зависящий от локали, для изменения регистра строк и символов. Текущие функции API toLowerCase(), toUpperCase(), capitalize(), decapitalize() зависят от локали. Это означает, что настройки локали разных платформ могут влиять на поведение кода. Например, в турецкой локали при преобразовании строки "kotlin" с помощью toUpperCase получается "KOTLİN", а не "KOTLIN".
// current API
println("Needs to be capitalized".toUpperCase()) // NEEDS TO BE CAPITALIZED
// new API
println("Needs to be capitalized".uppercase()) // NEEDS TO BE CAPITALIZED
В Kotlin 1.4.30 доступны следующие альтернативы:
-
Для функций
String:Предыдущие версии
Альтернатива в версии 1.4.30
String.toUpperCase()String.uppercase()String.toLowerCase()String.lowercase()String.capitalize()String.replaceFirstChar { it.uppercase() }String.decapitalize()String.replaceFirstChar { it.lowercase() } -
Для функций
Char:Предыдущие версии
Альтернатива в версии 1.4.30
Char.toUpperCase()Char.uppercaseChar(): CharChar.uppercase(): StringChar.toLowerCase()Char.lowercaseChar(): CharChar.lowercase(): StringChar.toTitleCase()Char.titlecaseChar(): CharChar.titlecase(): String
Полный список изменений функций обработки текста см. в KEEP.
Однозначные преобразования Char в код и Char в цифру
Текущие функции преобразования Char в числа, которые возвращают коды UTF-16 в различных числовых типах, часто путают с похожим преобразованием String в Int, которое возвращает числовое значение строки:
"4".toInt() // returns 4 '4'.toInt() // returns 52 // and there was no common function that would return the numeric value 4 for Char '4'
Чтобы избежать путаницы, мы решили разделить преобразования Char на два набора функций с понятными названиями:
-
Функции для получения целочисленного кода
Charи созданияCharпо заданному коду:fun Char(code: Int): Char fun Char(code: UShort): Char val Char.code: Int
-
Функции для преобразования
Charв числовое значение представляемой ею цифры:fun Char.digitToInt(radix: Int): Int fun Char.digitToIntOrNull(radix: Int): Int?
-
Функция расширения для
Int, преобразующая представляемую ею неотрицательную однозначную цифру в соответствующее представлениеChar:fun Int.digitToChar(radix: Int): Char
Подробнее см. в KEEP.
Обновления сериализации
Вместе с Kotlin 1.4.30 мы выпускаем kotlinx.serialization 1.1.0-RC, включающую несколько новых возможностей:
Поддержка сериализации inline-классов
Поддержка сериализации беззнаковых примитивных типов
Поддержка сериализации inline-классов
Начиная с Kotlin 1.4.30, inline-классы можно сделать сериализуемыми:
@Serializable inline class Color(val rgb: Int)
Среда сериализации не упаковывает сериализуемые inline-классы, когда они используются в других сериализуемых классах.
Подробнее см. в kotlinx.serialization документации.
Поддержка сериализации беззнаковых примитивных типов
Начиная с версии 1.4.30, для беззнаковых примитивных типов можно использовать стандартные сериализаторы JSON из kotlinx.serialization: UInt, ULong, UByte и UShort:
@Serializable
class Counter(val counted: UByte, val description: String)
fun main() {
val counted = 239.toUByte()
println(Json.encodeToString(Counter(counted, "tries")))
}
Подробнее см. в kotlinx.serialization документации.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew1430.html