Что нового в Kotlin 1.5.30
В Kotlin 1.5.30 представлены обновления языка, включая предварительные версии будущих изменений, различные улучшения поддержки платформ и инструментов, а также новые функции стандартной библиотеки.
Вот некоторые важные улучшения:
Возможности языка, включая экспериментальные инструкции sealed
when, изменения в использовании требований opt-in и другиеПоддержка Apple silicon
Бэкенд Kotlin/JS IR достиг стадии Beta
Улучшения работы с плагином Gradle
Краткий обзор изменений также представлен в публикации о выпуске и в этом видео:
Возможности языка
В Kotlin 1.5.30 представлены предварительные версии будущих изменений языка, а также улучшения механизма требований opt-in и вывода типов:
Требование opt-in для неявного использования экспериментальных API
Изменения в использовании аннотаций требований opt-in с разными целями
Полные инструкции when для субъектов sealed и Boolean
Полная инструкция when содержит ветви для всех возможных типов или значений своего субъекта либо для определённых типов и ветвь else, охватывающую все оставшиеся случаи.
В ближайшее время мы планируем запретить неполные инструкции when, чтобы их поведение соответствовало выражениям when. Для обеспечения плавного перехода можно настроить компилятор так, чтобы он выдавал предупреждения о неполных инструкциях when с sealed-классом или Boolean. По умолчанию такие предупреждения появятся в Kotlin 1.6, а позднее станут ошибками.
sealed class Mode {
object ON : Mode()
object OFF : Mode()
}
fun main() {
val x: Mode = Mode.ON
when (x) {
Mode.ON -> println("ON")
}
// WARNING: Non exhaustive 'when' statements on sealed classes/interfaces
// will be prohibited in 1.7, add an 'OFF' or 'else' branch instead
val y: Boolean = true
when (y) {
true -> println("true")
}
// WARNING: Non exhaustive 'when' statements on Booleans will be prohibited
// in 1.7, add a 'false' or 'else' branch instead
}
Чтобы включить эту возможность в Kotlin 1.5.30, используйте версию языка 1.6. Также можно преобразовать предупреждения в ошибки, включив прогрессивный режим.
kotlin {
sourceSets.all {
languageSettings.apply {
languageVersion = "1.6"
//progressiveMode = true // false by default
}
}
}
kotlin {
sourceSets.all {
languageSettings {
languageVersion = '1.6'
//progressiveMode = true // false by default
}
}
}
Функции-приостановки в качестве супертипов
В Kotlin 1.5.30 представлена предварительная версия возможности использовать функциональный тип suspend в качестве супертипа с некоторыми ограничениями.
class MyClass: suspend () -> Unit {
override suspend fun invoke() { TODO() }
}
Чтобы включить эту возможность, используйте параметр компилятора -language-version 1.6:
kotlin {
sourceSets.all {
languageSettings.apply {
languageVersion = "1.6"
}
}
}
kotlin {
sourceSets.all {
languageSettings {
languageVersion = '1.6'
}
}
}
У этой возможности есть следующие ограничения:
Нельзя смешивать обычный функциональный тип и функциональный тип
suspendв качестве супертипов. Это связано с особенностями реализации функциональных типовsuspendв бэкенде JVM. Они представляются в нём как обычные функциональные типы с интерфейсом-маркером. Из-за интерфейса-маркера невозможно определить, какие супер-интерфейсы являются приостанавливающими, а какие — обычными.Нельзя использовать несколько функциональных супертипов
suspend. Если выполняются проверки типов, также нельзя использовать несколько обычных функциональных супертипов.
Требование opt-in для неявного использования экспериментальных API
Автор библиотеки может пометить экспериментальный API как требующий opt-in, чтобы сообщить пользователям о его экспериментальном статусе. Компилятор выдаёт предупреждение или ошибку при использовании такого API и требует явного согласия, чтобы подавить его.
В Kotlin 1.5.30 компилятор считает экспериментальным любое объявление, в сигнатуре которого используется экспериментальный тип. То есть opt-in требуется даже для неявного использования экспериментального API. Например, если тип возвращаемого значения функции помечен как элемент экспериментального API, для использования этой функции требуется выполнить opt-in, даже если само объявление явно не помечено как требующее opt-in.
// Library code
@RequiresOptIn(message = "This API is experimental.")
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.CLASS)
annotation class MyDateTime // Opt-in requirement annotation
@MyDateTime
class DateProvider // A class requiring opt-in
// Client code
// Warning: experimental API usage
fun createDateSource(): DateProvider { /* ... */ }
fun getDate(): Date {
val dateSource = createDateSource() // Also warning: experimental API usage
// ...
}
Подробнее см. в разделе Требования opt-in.
Изменения в использовании аннотаций требований opt-in с разными целями
В Kotlin 1.5.30 представлены новые правила использования и объявления аннотаций требований opt-in с разными целями. Теперь компилятор сообщает об ошибке в случаях, обработка которых во время компиляции нецелесообразна. В Kotlin 1.5.30:
Запрещено помечать локальные переменные и параметры-значения аннотациями требований opt-in в месте использования.
Переопределение разрешено помечать только в том случае, если помечено и его базовое объявление.
Запрещено помечать поля для хранения и геттеры. Вместо этого можно пометить само базовое свойство.
Запрещено задавать цели аннотаций
TYPEиTYPE_PARAMETERв месте объявления аннотации требования opt-in.
Подробнее см. в разделе Требования opt-in.
Улучшения вывода типов для рекурсивных обобщённых типов
В Kotlin и Java можно определить рекурсивный обобщённый тип, который ссылается на себя в своих параметрах типа. В Kotlin 1.5.30 компилятор Kotlin может вывести аргумент типа, опираясь только на верхние границы соответствующего параметра типа, если он является рекурсивным обобщённым типом. Это позволяет создавать различные шаблоны с рекурсивными обобщёнными типами, которые часто используются в Java для построения API-конструкторов.
// Kotlin 1.5.20
val containerA = PostgreSQLContainer<Nothing>(DockerImageName.parse("postgres:13-alpine")).apply {
withDatabaseName("db")
withUsername("user")
withPassword("password")
withInitScript("sql/schema.sql")
}
// Kotlin 1.5.30
val containerB = PostgreSQLContainer(DockerImageName.parse("postgres:13-alpine"))
.withDatabaseName("db")
.withUsername("user")
.withPassword("password")
.withInitScript("sql/schema.sql")
Улучшения можно включить с помощью параметра компилятора -Xself-upper-bound-inference или -language-version 1.6. Другие примеры новых поддерживаемых сценариев использования см. в этой задаче YouTrack.
Снятие ограничений на вывод типов в конструкторах
Вывод типов в конструкторах — это особый вид вывода типов, который позволяет выводить аргументы типа вызова на основе информации о типах из других вызовов внутри его лямбда-аргумента. Это может быть полезно при вызове обобщённых функций-конструкторов, таких как buildList() или sequence(): buildList { add("string") }.
Ранее внутри такого лямбда-аргумента действовало ограничение на использование информации о типах, которую пытается вывести механизм вывода типов в конструкторах. Это означает, что тип можно было только указать, но нельзя было получить. Например, внутри лямбда-аргумента buildList() нельзя было вызвать get() без явного указания аргументов типа.
В Kotlin 1.5.30 эти ограничения снимаются с помощью параметра компилятора -Xunrestricted-builder-inference. Добавьте этот параметр, чтобы разрешить ранее запрещённые вызовы внутри лямбда-аргумента обобщённых функций-конструкторов:
@kotlin.ExperimentalStdlibApi
val list = buildList {
add("a")
add("b")
set(1, null)
val x = get(1)
if (x != null) {
removeAt(1)
}
}
@kotlin.ExperimentalStdlibApi
val map = buildMap {
put("a", 1)
put("b", 1.1)
put("c", 2f)
}
Эту возможность также можно включить с помощью параметра компилятора -language-version 1.6.
Kotlin/JVM
В Kotlin 1.5.30 для Kotlin/JVM доступны следующие возможности:
Обновления плагина Kotlin Gradle для платформы JVM см. в разделе Gradle.
Создание экземпляров классов аннотаций
Начиная с Kotlin 1.5.30, можно вызывать конструкторы классов аннотаций в произвольном коде, чтобы получить экземпляр. Эта возможность охватывает те же сценарии использования, что и соглашение Java, позволяющее реализовывать интерфейс аннотации.
annotation class InfoMarker(val info: String)
fun processInfo(marker: InfoMarker) = ...
fun main(args: Array<String>) {
if (args.size != 0)
processInfo(getAnnotationReflective(args))
else
processInfo(InfoMarker("default"))
}
Чтобы включить эту возможность, используйте параметр компилятора -language-version 1.6. Обратите внимание, что все существующие ограничения классов аннотаций остаются в силе, например запрет на объявление параметров, отличных от val, или членов, отличных от вторичных конструкторов.
Подробнее о создании экземпляров классов аннотаций см. в этом документе KEEP
Улучшенная настройка поддержки аннотаций nullability
Компилятор Kotlin может читать различные типы аннотаций nullability, чтобы получать информацию о nullability из Java. Благодаря этой информации он может сообщать о несоответствиях nullability в Kotlin при вызове кода Java.
В Kotlin 1.5.30 можно указать, должен ли компилятор сообщать о несоответствии nullability на основе информации из определённых типов аннотаций nullability. Для этого используйте параметр компилятора -Xnullability-annotations=@<package-name>:<report-level>. В аргументе укажите полное имя пакета аннотаций nullability и один из следующих уровней отчётности:
ignore— игнорировать несоответствия nullabilitywarn— выдавать предупрежденияstrict— выдавать ошибки.
Полный список поддерживаемых аннотаций nullability вместе с полными именами пакетов см. здесь.
Пример включения сообщений об ошибках для новых аннотаций nullability в RxJava 3: -Xnullability-annotations=@io.reactivex.rxjava3.annotations:strict. Обратите внимание, что по умолчанию все такие несоответствия nullability являются предупреждениями.
Kotlin/Native
В Kotlin/Native появились различные изменения и улучшения:
Улучшенное сопоставление объектов и объектов-компаньонов со Swift/Objective-C
Отказ от связывания с DLL без библиотек импорта для целей MinGW
Поддержка Apple silicon
В Kotlin 1.5.30 добавлена нативная поддержка Apple silicon.
Ранее для работы компилятора и инструментов Kotlin/Native на компьютерах Apple silicon требовалась среда трансляции Rosetta. В Kotlin 1.5.30 среда трансляции больше не нужна — компилятор и инструменты могут работать на оборудовании Apple silicon без дополнительных действий.
Мы также добавили новые цели, которые позволяют запускать код Kotlin нативно на Apple silicon:
macosArm64iosSimulatorArm64watchosSimulatorArm64tvosSimulatorArm64
Они доступны как на компьютерах Intel, так и на Apple silicon. Все существующие цели также доступны на компьютерах Apple silicon.
Обратите внимание, что в версии 1.5.30 плагин Gradle kotlin-multiplatform обеспечивает только базовую поддержку целей Apple silicon. В частности, новые цели симулятора не включены в сокращённые обозначения целей ios, tvos и watchos. Мы продолжим работу над улучшением пользовательского опыта с новыми целями.
Улучшенный Kotlin DSL для плагина CocoaPods Gradle
Новые параметры фреймворков Kotlin/Native
В Kotlin 1.5.30 улучшен DSL плагина CocoaPods Gradle для фреймворков Kotlin/Native. Помимо имени фреймворка, в конфигурации Pod можно указать другие параметры:
Указать динамический или статический вариант фреймворка
Явно включить экспорт зависимостей
Включить встраивание Bitcode
Чтобы использовать новый DSL, обновите проект до Kotlin 1.5.30 и укажите параметры в разделе cocoapods файла build.gradle(.kts):
cocoapods {
frameworkName = "MyFramework" // This property is deprecated
// and will be removed in future versions
// New DSL for framework configuration:
framework {
// All Framework properties are supported
// Framework name configuration. Use this property instead of
// deprecated 'frameworkName'
baseName = "MyFramework"
// Dynamic framework support
isStatic = false
// Dependency export
export(project(":anotherKMMModule"))
transitiveExport = false // This is default.
// Bitcode embedding
embedBitcode(BITCODE)
}
}
Поддержка пользовательских имён конфигураций Xcode
Плагин Kotlin CocoaPods Gradle поддерживает пользовательские имена в конфигурации сборки Xcode. Это также пригодится, если вы используете в Xcode специальные имена для конфигурации сборки, например Staging.
Чтобы указать пользовательское имя, используйте параметр xcodeConfigurationToNativeBuildType в разделе cocoapods файла build.gradle(.kts):
cocoapods {
// Maps custom Xcode configuration to NativeBuildType
xcodeConfigurationToNativeBuildType["CUSTOM_DEBUG"] = NativeBuildType.DEBUG
xcodeConfigurationToNativeBuildType["CUSTOM_RELEASE"] = NativeBuildType.RELEASE
}
Этот параметр не появится в файле Podspec. Когда Xcode запускает процесс сборки Gradle, плагин Kotlin CocoaPods Gradle выбирает необходимый тип нативной сборки.
Экспериментальная совместимость со Swift 5.5 async/await
В версии 1.4.0 мы добавили поддержку вызова функций-приостановок Kotlin из Objective-C и Swift, а теперь улучшаем её с учётом новой возможности Swift 5.5 — параллельного выполнения с модификаторами async и await.
Теперь компилятор Kotlin/Native добавляет атрибут _Nullable_result в сгенерированные заголовки Objective-C для функций-приостановок с nullable-типами возвращаемого значения. Благодаря этому их можно вызывать из Swift как функции async с корректной nullability.
Обратите внимание, что эта возможность является экспериментальной и в будущем на неё могут повлиять изменения как в Kotlin, так и в Swift. Пока мы предлагаем предварительную версию с определёнными ограничениями и будем рады узнать ваше мнение. Подробнее о текущем состоянии и оставьте отзыв в этой задаче YouTrack.
Улучшенное сопоставление объектов и объектов-компаньонов со Swift/Objective-C
Теперь доступ к объектам и объектам-компаньонам можно получать способом, более интуитивным для разработчиков нативных приложений iOS. Например, если в Kotlin у вас есть следующие объекты:
object MyObject {
val x = "Some value"
}
class MyClass {
companion object {
val x = "Some value"
}
}
Чтобы получить к ним доступ в Swift, можно использовать свойства shared и companion:
MyObject.shared MyObject.shared.x MyClass.companion MyClass.Companion.shared
Подробнее о совместимости Swift/Objective-C.
Отказ от связывания с DLL без библиотек импорта для целей MinGW
LLD — это компоновщик проекта LLVM, который мы планируем начать использовать в Kotlin/Native для целей MinGW благодаря его преимуществам перед стандартным ld.bfd, прежде всего более высокой производительности.
Однако последняя стабильная версия LLD не поддерживает прямое связывание с DLL для целей MinGW (Windows). Для такого связывания требуются библиотеки импорта. Хотя в Kotlin/Native 1.5.30 они не нужны, мы добавляем предупреждение, чтобы сообщить вам, что такой способ использования несовместим с LLD, который в будущем станет компоновщиком по умолчанию для MinGW.
Поделитесь своими мыслями и опасениями по поводу перехода на компоновщик LLD в этой задаче YouTrack.
Kotlin Multiplatform
В версии 1.5.30 появились следующие важные обновления Kotlin Multiplatform:
Возможность использовать пользовательские библиотеки cinterop в общем нативном коде
Kotlin Multiplatform предоставляет возможность использовать платформозависимые библиотеки взаимодействия в общих исходных наборах. До версии 1.5.30 это работало только с библиотеками платформы, поставляемыми вместе с дистрибутивом Kotlin/Native. Начиная с версии 1.5.30 вы можете использовать эту возможность с пользовательскими библиотеками cinterop. Чтобы включить эту функцию, добавьте свойство kotlin.mpp.enableCInteropCommonization=true в файл gradle.properties:
kotlin.mpp.enableGranularSourceSetsMetadata=true kotlin.native.enableDependencyPropagation=false kotlin.mpp.enableCInteropCommonization=true
Поддержка XCFrameworks
Теперь во всех проектах Kotlin Multiplatform XCFrameworks можно использовать в качестве выходного формата. Apple представила XCFrameworks как замену универсальным (fat) фреймворкам. Благодаря XCFrameworks вы можете:
Собрать логику для всех целевых платформ и архитектур в один пакет.
Не удалять все ненужные архитектуры перед публикацией приложения в App Store.
XCFrameworks полезны, если вы хотите использовать свой фреймворк Kotlin на устройствах и симуляторах Apple M1.
Чтобы использовать XCFrameworks, обновите скрипт build.gradle(.kts):
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework
plugins {
kotlin("multiplatform")
}
kotlin {
val xcf = XCFramework()
ios {
binaries.framework {
baseName = "shared"
xcf.add(this)
}
}
watchos {
binaries.framework {
baseName = "shared"
xcf.add(this)
}
}
tvos {
binaries.framework {
baseName = "shared"
xcf.add(this)
}
}
}
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFrameworkConfig
plugins {
id 'org.jetbrains.kotlin.multiplatform'
}
kotlin {
def xcf = new XCFrameworkConfig(project)
ios {
binaries.framework {
baseName = "shared"
xcf.add(it)
}
}
watchos {
binaries.framework {
baseName = "shared"
xcf.add(it)
}
}
tvos {
binaries.framework {
baseName = "shared"
xcf.add(it)
}
}
}
При объявлении XCFrameworks будут зарегистрированы следующие новые задачи Gradle:
assembleXCFrameworkassembleDebugXCFramework(дополнительный отладочный артефакт, который содержит dSYM)assembleReleaseXCFramework
Подробнее о XCFrameworks можно узнать в этом видео WWDC.
Новая настройка публикации артефактов Android по умолчанию
С помощью плагина Gradle maven-publish вы можете опубликовать свою мультиплатформенную библиотеку для целевой платформы Android, указав имена вариантов Android в скрипте сборки. Плагин Kotlin Gradle автоматически создаст публикации.
До версии 1.5.30 в метаданные метаданные сгенерированной публикации включались атрибуты типа сборки для каждого публикуемого варианта Android, поэтому она была совместима только с тем же типом сборки, который использовал потребитель библиотеки. В Kotlin 1.5.30 появилась новая настройка публикации по умолчанию:
Если у всех публикуемых проектом вариантов Android одинаковое значение атрибута типа сборки, опубликованные варианты не будут содержать этот атрибут и будут совместимы с любым типом сборки.
Если у опубликованных вариантов разные значения атрибута типа сборки, то без этого атрибута будут опубликованы только варианты со значением
release. Благодаря этому варианты release будут совместимы с любым типом сборки на стороне потребителя, а варианты, отличные от release, будут совместимы только с соответствующими типами сборки потребителя.
Чтобы отказаться от этого поведения и сохранить атрибуты типа сборки для всех вариантов, задайте следующее свойство Gradle: kotlin.android.buildTypeAttribute.keep=true.
Kotlin/JS
В версии 1.5.30 в Kotlin/JS появятся два важных улучшения:
Бэкенд компилятора JS IR достиг стадии Beta
Бэкенд компилятора на основе IR для Kotlin/JS, представленный в версии 1.4.0 на стадии Alpha, достиг стадии Beta.
Ранее мы опубликовали руководство по миграции на бэкенд JS IR, чтобы помочь вам перенести проекты на новый бэкенд. Теперь мы хотим представить плагин IDE Kotlin/JS Inspection Pack, который показывает необходимые изменения непосредственно в IntelliJ IDEA.
Улучшенная отладка приложений с бэкендом Kotlin/JS IR
В Kotlin 1.5.30 появилась генерация карт исходного кода JavaScript для бэкенда Kotlin/JS IR. Это улучшит отладку Kotlin/JS при включенном бэкенде IR: будут доступны точки останова, пошаговое выполнение и читаемые трассировки стека с корректными ссылками на исходный код.
Узнайте, как отлаживать Kotlin/JS в браузере или IntelliJ IDEA.
Gradle
В рамках нашей работы над улучшением взаимодействия пользователей с плагином Kotlin Gradle мы реализовали следующие функции:
Поддержка цепочек инструментов Java, в том числе возможность указать каталог JDK с помощью интерфейса
UsesKotlinJavaToolchainв старых версиях GradleБолее простой способ явно указать аргументы JVM для демона Kotlin
Поддержка цепочек инструментов Java
В Gradle 6.7 появилась функция «Поддержка цепочек инструментов Java». С ее помощью можно:
Выполнять компиляцию, тесты и исполняемые файлы с помощью JDK и JRE, отличных от используемых Gradle.
Компилировать и тестировать код с еще не выпущенной версией языка.
При поддержке цепочек инструментов Gradle может автоматически обнаруживать локальные JDK и устанавливать недостающие JDK, необходимые для сборки. Теперь сам Gradle может работать с любой JDK и при этом повторно использовать кэш сборки.
Плагин Kotlin Gradle поддерживает цепочки инструментов Java для задач компиляции Kotlin/JVM. Цепочка инструментов Java:
-
Задает параметр
jdkHome, доступный для целей JVM. Задает значение
kotlinOptions.jvmTarget, соответствующее версии JDK из цепочки инструментов, если пользователь явно не задал параметрjvmTarget. Если цепочка инструментов не настроена, для поляjvmTargetиспользуется значение по умолчанию. Подробнее о совместимости целевых платформ JVM.Влияет на то, в какой JDK выполняются рабочие процессы
kapt.
Чтобы задать цепочку инструментов, используйте следующий код. Замените заполнитель <MAJOR_JDK_VERSION> версией JDK, которую хотите использовать:
kotlin {
jvmToolchain {
(this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // "8"
}
}
kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // "8"
}
}
Обратите внимание: настройка цепочки инструментов через расширение kotlin также обновит цепочку инструментов для задач компиляции Java.
Можно настроить цепочку инструментов через расширение java, и задачи компиляции Kotlin будут ее использовать:
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // "8"
}
}
Информацию о настройке любой версии JDK для задач KotlinCompile см. в документации о настройке версии JDK с помощью Task DSL.
Для версий Gradle от 6.1 до 6.6 используйте интерфейс UsesKotlinJavaToolchain, чтобы задать каталог JDK.
Возможность указать каталог JDK с помощью интерфейса UsesKotlinJavaToolchain
Все задачи Kotlin, поддерживающие настройку JDK через kotlinOptions, теперь реализуют интерфейс UsesKotlinJavaToolchain. Чтобы задать каталог JDK, укажите путь к JDK вместо заполнителя <JDK_VERSION>:
project.tasks
.withType<UsesKotlinJavaToolchain>()
.configureEach {
it.kotlinJavaToolchain.jdk.use(
"/path/to/local/jdk",
JavaVersion.<LOCAL_JDK_VERSION>
)
}
project.tasks
.withType(UsesKotlinJavaToolchain.class)
.configureEach {
it.kotlinJavaToolchain.jdk.use(
'/path/to/local/jdk',
JavaVersion.<LOCAL_JDK_VERSION>
)
}
Используйте интерфейс UsesKotlinJavaToolchain для версий Gradle от 6.1 до 6.6. Начиная с Gradle 6.7 вместо него используйте цепочки инструментов Java.
При использовании этой функции учтите, что рабочие процессы задач kapt будут использовать только режим изоляции процессов, а свойство kapt.workers.isolation будет игнорироваться.
Более простой способ явно указать аргументы JVM для демона Kotlin
В Kotlin 1.5.30 появилась новая логика обработки аргументов JVM демона Kotlin. Каждый параметр в следующем списке переопределяет параметры, указанные перед ним:
-
Если ничего не указано, демон Kotlin наследует аргументы демона Gradle (как и раньше). Например, в файле
gradle.properties:org.gradle.jvmargs=-Xmx1500m -Xms=500m
-
Если аргументы JVM демона Gradle содержат системное свойство
kotlin.daemon.jvm.options, оно используется, как и раньше:org.gradle.jvmargs=-Dkotlin.daemon.jvm.options=-Xmx1500m -Xms=500m
-
Можно добавить свойство
kotlin.daemon.jvmargsв файлgradle.properties:kotlin.daemon.jvmargs=-Xmx1500m -Xms=500m
-
Можно указать аргументы в расширении
kotlin:kotlin { kotlinDaemonJvmArgs = listOf("-Xmx486m", "-Xms256m", "-XX:+UseParallelGC") }kotlin { kotlinDaemonJvmArgs = ["-Xmx486m", "-Xms256m", "-XX:+UseParallelGC"] } -
Можно указать аргументы для конкретной задачи:
tasks .matching { it.name == "compileKotlin" && it is CompileUsingKotlinDaemon } .configureEach { (this as CompileUsingKotlinDaemon).kotlinDaemonJvmArguments.set(listOf("-Xmx486m", "-Xms256m", "-XX:+UseParallelGC")) }tasks .matching { it.name == "compileKotlin" && it instanceof CompileUsingKotlinDaemon } .configureEach { kotlinDaemonJvmArguments.set(["-Xmx1g", "-Xms512m"]) }
Дополнительную информацию о демоне Kotlin см. в разделе Демон Kotlin и его использование с Gradle.
Стандартная библиотека
В Kotlin 1.5.30 улучшены API Duration и Regex стандартной библиотеки:
Изменение результата Duration.toString()
До Kotlin 1.5.30 функция Duration.toString() возвращала строковое представление аргумента в единице измерения, позволяющей получить наиболее компактное и понятное числовое значение. Теперь она возвращает строковое значение в виде комбинации числовых компонентов, каждый из которых выражен в своей единице измерения. Каждый компонент — это число, за которым следует сокращенное название единицы измерения: d, h, m, s. Например:
Пример вызова функции |
Предыдущий результат |
Текущий результат |
|---|---|---|
Duration.days(45).toString() |
|
|
Duration.days(1.5).toString() |
|
|
Duration.minutes(1230).toString() |
|
|
Duration.minutes(2415).toString() |
|
|
Duration.minutes(920).toString() |
|
|
Duration.seconds(1.546).toString() |
|
|
Duration.milliseconds(25.12).toString() |
|
|
Изменился и способ представления отрицательных длительностей. Отрицательная длительность начинается со знака минус (-), а если она состоит из нескольких компонентов, то заключается в скобки: -12m и -(1h 30m).
Обратите внимание, что небольшие длительности менее одной секунды представляются одним числом с одной из единиц измерения меньше секунды. Например, ms (миллисекунды), us (микросекунды) или ns (наносекунды): 140.884ms, 500us, 24ns. Научная нотация для их представления больше не используется.
Чтобы представить длительность в одной единице измерения, используйте перегруженную функцию Duration.toString(unit, decimals).
Разбор Duration из строки
В Kotlin 1.5.30 в API Duration появились новые функции:
-
parse(), которая поддерживает разбор результатов: parseIsoString(), которая разбирает только строки в формате, создаваемом функциейtoIsoString().parseOrNull()иparseIsoStringOrNull(), которые работают как описанные выше функции, но возвращаютnullвместо того, чтобы выбрасыватьIllegalArgumentExceptionпри недопустимом формате длительности.
Примеры использования parse() и parseOrNull():
import kotlin.time.Duration
import kotlin.time.ExperimentalTime
@ExperimentalTime
fun main() {
//sampleStart
val isoFormatString = "PT1H30M"
val defaultFormatString = "1h 30m"
val singleUnitFormatString = "1.5h"
val invalidFormatString = "1 hour 30 minutes"
println(Duration.parse(isoFormatString)) // "1h 30m"
println(Duration.parse(defaultFormatString)) // "1h 30m"
println(Duration.parse(singleUnitFormatString)) // "1h 30m"
//println(Duration.parse(invalidFormatString)) // throws exception
println(Duration.parseOrNull(invalidFormatString)) // "null"
//sampleEnd
}
А вот примеры использования parseIsoString() и parseIsoStringOrNull():
import kotlin.time.Duration
import kotlin.time.ExperimentalTime
@ExperimentalTime
fun main() {
//sampleStart
val isoFormatString = "PT1H30M"
val defaultFormatString = "1h 30m"
println(Duration.parseIsoString(isoFormatString)) // "1h 30m"
//println(Duration.parseIsoString(defaultFormatString)) // throws exception
println(Duration.parseIsoStringOrNull(defaultFormatString)) // "null"
//sampleEnd
}
Поиск совпадения с Regex в заданной позиции
Новые функции Regex.matchAt() и Regex.matchesAt() позволяют проверить, есть ли точное совпадение с регулярным выражением в заданной позиции в String или CharSequence.
Функция matchesAt() возвращает логическое значение:
fun main(){
//sampleStart
val releaseText = "Kotlin 1.5.30 is released!"
// regular expression: one digit, dot, one digit, dot, one or more digits
val versionRegex = "\\d[.]\\d[.]\\d+".toRegex()
println(versionRegex.matchesAt(releaseText, 0)) // "false"
println(versionRegex.matchesAt(releaseText, 7)) // "true"
//sampleEnd
}
Функция matchAt() возвращает совпадение, если оно найдено, или null, если совпадения нет:
fun main(){
//sampleStart
val releaseText = "Kotlin 1.5.30 is released!"
val versionRegex = "\\d[.]\\d[.]\\d+".toRegex()
println(versionRegex.matchAt(releaseText, 0)) // "null"
println(versionRegex.matchAt(releaseText, 7)?.value) // "1.5.30"
//sampleEnd
}
Разбиение Regex в последовательность
Новая функция Regex.splitToSequence() — это ленивый аналог функции split(). Она разбивает строку по совпадениям с заданным регулярным выражением, но возвращает результат в виде Sequence, поэтому все операции с результатом выполняются лениво.
fun main(){
//sampleStart
val colorsText = "green, red , brown&blue, orange, pink&green"
val regex = "[,\\s]+".toRegex()
val mixedColor = regex.splitToSequence(colorsText)
.onEach { println(it) }
.firstOrNull { it.contains('&') }
println(mixedColor) // "brown&blue"
//sampleEnd
}
Похожая функция также добавлена в CharSequence:
val mixedColor = colorsText.splitToSequence(regex)
Serialization 1.3.0-RC
Выпущена kotlinx.serialization версия 1.3.0-RC с новыми возможностями сериализации JSON:
Сериализация потоков Java IO
Управление значениями по умолчанию на уровне свойств
Возможность исключать значения null из сериализации
Пользовательские дискриминаторы классов при полиморфной сериализации
Подробнее см. в списке изменений.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew1530.html