Что нового в Kotlin 1.8.0
Вышел Kotlin 1.8.0. Вот некоторые из главных нововведений:
Новые экспериментальные функции для JVM: рекурсивное копирование или удаление содержимого каталогов
kotlin-stdlib-jdk7иkotlin-stdlib-jdk8объединены вkotlin-stdlib
Поддержка IDE
Плагин Kotlin с поддержкой версии 1.8.0 доступен для:
IDE |
Поддерживаемые версии |
|---|---|
IntelliJ IDEA |
2021.3, 2022.1, 2022.2 |
Android Studio |
Electric Eel (221), Flamingo (222) |
Kotlin/JVM
Начиная с версии 1.8.0, компилятор может генерировать классы с версией байт-кода, соответствующей JVM 19. Новая версия языка также включает:
Параметр компилятора для отключения генерации целей аннотаций JVM
Новый параметр компилятора
-Xdebugдля отключения оптимизаций
Возможность не генерировать цели аннотаций TYPE_USE и TYPE_PARAMETER
Если среди целей Kotlin-аннотации указана TYPE, эта аннотация отображается в java.lang.annotation.ElementType.TYPE_USE в списке целей Java-аннотаций. Это аналогично тому, как цель Kotlin TYPE_PARAMETER отображается в цель Java java.lang.annotation.ElementType.TYPE_PARAMETER. Это создает проблему для клиентов Android с уровнями API ниже 26, в API которых такие цели отсутствуют.
Начиная с Kotlin 1.8.0, можно использовать новый параметр компилятора -Xno-new-java-annotation-targets, чтобы не генерировать цели аннотаций TYPE_USE и TYPE_PARAMETER.
Новый параметр компилятора для отключения оптимизаций
В Kotlin 1.8.0 добавлен новый параметр компилятора -Xdebug, который отключает оптимизации и тем самым упрощает отладку. Пока этот параметр отключает для корутин функцию «was optimized out». В будущем, после добавления новых оптимизаций, этот параметр будет отключать и их.
Функция «was optimized out» оптимизирует переменные при использовании suspend-функций. Однако отлаживать код с оптимизированными переменными сложно, поскольку их значения не отображаются.
Удаление старого бэкенда
В Kotlin 1.5.0 мы объявили, что бэкенд на основе IR стал стабильным. Это означало, что старый бэкенд из Kotlin 1.4.* устарел. В Kotlin 1.8.0 мы полностью удалили старый бэкенд. Вместе с ним удалены параметр компилятора -Xuse-old-backend и параметр Gradle useOldBackend.
Поддержка аннотации Lombok @Builder
Сообщество оставило так много голосов за задачу YouTrack Kotlin Lombok: поддержка генерируемых конструкторов (@Builder), что мы просто обязаны были добавить поддержку аннотации @Builder.
Пока мы не планируем поддерживать аннотации @SuperBuilder или @Tolerate, но пересмотрим это решение, если за задачи @SuperBuilder и @Tolerate проголосует достаточно людей.
Kotlin/Native
В Kotlin 1.8.0 добавлены изменения, касающиеся совместимости с Objective-C и Swift, поддержка Xcode 14.1 и улучшения плагина CocoaPods Gradle:
Поддержка Xcode 14.1
Теперь компилятор Kotlin/Native поддерживает последнюю стабильную версию Xcode — 14.1. Улучшения совместимости включают следующие изменения:
Добавлен новый пресет
watchosDeviceArm64для целевой платформы watchOS, который поддерживает Apple watchOS на платформах ARM64.В плагине Kotlin CocoaPods Gradle по умолчанию больше не встраивается битовый код во фреймворки Apple.
Библиотеки платформ обновлены с учетом изменений во фреймворках Objective-C для целевых платформ Apple.
Улучшенная совместимость с Objective-C и Swift
Чтобы улучшить совместимость Kotlin с Objective-C и Swift, добавлены три новые аннотации:
-
@ObjCNameпозволяет указать более идиоматичное имя в Swift или Objective-C вместо переименования объявления Kotlin.Аннотация указывает компилятору Kotlin использовать пользовательское имя Objective-C и Swift для этого класса, свойства, параметра или функции:
@ObjCName(swiftName = "MySwiftArray") class MyKotlinArray { @ObjCName("index") fun indexOf(@ObjCName("of") element: String): Int = TODO() } // Usage with the ObjCName annotations let array = MySwiftArray() let index = array.index(of: "element") -
@HiddenFromObjCпозволяет скрыть объявление Kotlin от Objective-C.Аннотация указывает компилятору Kotlin не экспортировать функцию или свойство в Objective-C, а следовательно, и в Swift. Это позволяет сделать код Kotlin более удобным для использования из Objective-C и Swift.
-
@ShouldRefineInSwiftполезна для замены объявления Kotlin оберткой, написанной на Swift.Аннотация указывает компилятору Kotlin пометить функцию или свойство как
swift_privateв сгенерированном API Objective-C. Такие объявления получают префикс__, из-за которого они не видны в коде Swift.Эти объявления по-прежнему можно использовать в коде Swift для создания удобного для Swift API, но, например, Xcode не будет предлагать их в автодополнении.
Подробнее об уточнении объявлений Objective-C в Swift см. в официальной документации Apple.
Команда Kotlin выражает большую благодарность Рику Клефасу за реализацию этих аннотаций.
Динамические фреймворки по умолчанию в плагине CocoaPods Gradle
Начиная с Kotlin 1.8.0, фреймворки Kotlin, зарегистрированные плагином CocoaPods Gradle, по умолчанию связываются динамически. Предыдущая статическая реализация не соответствовала поведению плагина Kotlin Gradle.
kotlin {
cocoapods {
framework {
baseName = "MyFramework"
isStatic = false // Now dynamic by default
}
}
}
Если в существующем проекте используется статический тип связывания и вы обновите проект до Kotlin 1.8.0 (или явно измените тип связывания), при выполнении проекта может возникнуть ошибка. Чтобы устранить ее, закройте проект Xcode и выполните pod install в каталоге Podfile.
Подробнее см. в справочнике DSL плагина CocoaPods Gradle.
Kotlin Multiplatform: новая структура наборов исходного кода Android
В Kotlin 1.8.0 представлена новая структура наборов исходного кода Android, заменяющая прежнюю схему именования каталогов, которая во многих отношениях была неудобной.
Рассмотрим пример двух каталогов androidTest, созданных в текущей структуре. Один предназначен для KotlinSourceSets, а другой — для AndroidSourceSets:
У них разная семантика:
androidTestв Kotlin относится к типуunitTest, а в Android — к типуintegrationTest.Они создают запутанную структуру
SourceDirectories, поскольку уsrc/androidTest/kotlinестьUnitTest, а уsrc/androidTest/java—InstrumentedTest.И
KotlinSourceSets, иAndroidSourceSetsиспользуют схожую схему именования конфигураций Gradle, поэтому результирующие конфигурацииandroidTestдля наборов исходного кода Kotlin и Android совпадают:androidTestImplementation,androidTestApi,androidTestRuntimeOnlyиandroidTestCompileOnly.
Чтобы устранить эти и другие существующие проблемы, мы представили новую структуру наборов исходного кода Android. Вот некоторые ключевые различия между двумя структурами:
Схема именования KotlinSourceSet
Текущая структура наборов исходного кода |
Новая структура наборов исходного кода |
|---|---|
|
|
{AndroidSourceSet.name} сопоставляется с {KotlinSourceSet.name} следующим образом:
Текущая структура наборов исходного кода |
Новая структура наборов исходного кода |
|
|---|---|---|
main |
androidMain |
androidMain |
test |
androidTest |
androidUnitTest |
androidTest |
androidAndroidTest |
androidInstrumentedTest |
SourceDirectories
Текущая структура наборов исходного кода |
Новая структура наборов исходного кода |
|---|---|
Структура добавляет дополнительные SourceDirectories |
|
{AndroidSourceSet.name} сопоставляется с {SourceDirectories included} следующим образом:
Текущая структура наборов исходного кода |
Новая структура наборов исходного кода |
|
|---|---|---|
main |
src/androidMain/kotlin, src/main/kotlin, src/main/java |
src/androidMain/kotlin, src/main/kotlin, src/main/java |
test |
src/androidTest/kotlin, src/test/kotlin, src/test/java |
src/androidUnitTest/kotlin, src/test/kotlin, src/test/java |
androidTest |
src/androidAndroidTest/kotlin, src/androidTest/java |
src/androidInstrumentedTest/kotlin, src/androidTest/java, src/androidTest/kotlin |
Расположение файла AndroidManifest.xml
Текущая структура наборов исходного кода |
Новая структура наборов исходного кода |
|---|---|
src/{AndroidSourceSet.name}/AndroidManifest.xml |
src/{KotlinSourceSet.name}/AndroidManifest.xml |
{AndroidSourceSet.name} сопоставляется с {AndroidManifest.xml location} следующим образом:
Текущая структура наборов исходного кода |
Новая структура наборов исходного кода |
|
|---|---|---|
main |
src/main/AndroidManifest.xml |
src/androidMain/AndroidManifest.xml |
debug |
src/debug/AndroidManifest.xml |
src/androidDebug/AndroidManifest.xml |
Связь между тестами Android и общими тестами
Новая структура наборов исходного кода Android меняет связь между инструментированными тестами Android (в новой структуре они переименованы в androidInstrumentedTest) и общими тестами.
Ранее между androidAndroidTest и commonTest по умолчанию существовала связь dependsOn. На практике это означало следующее:
Код из
commonTestбыл доступен вandroidAndroidTest.Для объявлений
expectвcommonTestтребовались соответствующие реализацииactualвandroidAndroidTest.Тесты, объявленные в
commonTest, также запускались как инструментированные тесты Android.
В новой структуре наборов исходного кода Android связь dependsOn не добавляется по умолчанию. Если вам нужно прежнее поведение, объявите эту связь вручную в файле build.gradle.kts:
kotlin {
// ...
sourceSets {
val commonTest by getting
val androidInstrumentedTest by getting {
dependsOn(commonTest)
}
}
}
Поддержка вариантов Android
Ранее плагин Kotlin Gradle заранее создавал наборы исходного кода, соответствующие наборам исходного кода Android с типами сборки debug и release или пользовательскими вариантами, например demo и full. К ним можно было обращаться с помощью конструкций вроде val androidDebug by getting { ... }.
В новой структуре наборов исходного кода Android эти наборы создаются на этапе afterEvaluate. Поэтому такие выражения становятся недопустимыми и приводят к ошибкам, например org.gradle.api.UnknownDomainObjectException: KotlinSourceSet with name 'androidDebug' not found.
Чтобы обойти эту проблему, используйте новый API invokeWhenCreated() в файле build.gradle.kts:
kotlin {
// ...
sourceSets.invokeWhenCreated("androidFreeDebug") {
// ...
}
}
Настройка и конфигурация
В будущих выпусках новая структура станет использоваться по умолчанию. Вы можете включить ее уже сейчас с помощью следующего параметра Gradle:
kotlin.mpp.androidSourceSetLayoutVersion=2
Использование каталогов в прежнем стиле Android теперь не рекомендуется. В Kotlin 1.8.0 начинается цикл отказа от них: для текущей структуры будет выдаваться предупреждение. Его можно отключить с помощью следующего свойства Gradle:
kotlin.mpp.androidSourceSetLayoutVersion1.nowarn=true
Kotlin/JS
В Kotlin 1.8.0 бэкенд компилятора JS IR становится стабильным, а в скрипты сборки Gradle, связанные с JavaScript, добавляются новые возможности:
Стабильный бэкенд компилятора JS IR
Начиная с этого выпуска, бэкенд компилятора Kotlin/JS на основе промежуточного представления (IR) является стабильным. Унификация инфраструктуры для всех трех бэкендов заняла некоторое время, но теперь все они работают с одним и тем же IR для кода Kotlin.
В связи со стабилизацией бэкенда компилятора JS IR старый бэкенд теперь объявлен устаревшим.
Инкрементальная компиляция включена по умолчанию вместе со стабильным компилятором JS IR.
Если вы все еще используете старый компилятор, переключите проект на новый бэкенд.
Новые настройки для уведомлений об обновлении yarn.lock
Если вы используете менеджер пакетов yarn, доступны три новых специальных настройки Gradle, которые могут уведомлять об обновлении файла yarn.lock. Эти настройки пригодятся, если нужно получать уведомления о незаметных изменениях yarn.lock во время сборки CI.
Новые свойства Gradle:
-
YarnLockMismatchReport— задает способ уведомления об изменениях в файлеyarn.lock. Можно указать одно из следующих значений:FAILприводит к сбою соответствующей задачи Gradle. Это значение используется по умолчанию.WARNINGзаписывает сведения об изменениях в журнал предупреждений.NONEотключает уведомления.
reportNewYarnLock— явно сообщает о недавно созданном файлеyarn.lock. По умолчанию этот параметр отключен: обычно новый файлyarn.lockсоздается при первом запуске. Этот параметр можно использовать, чтобы проверить, был ли файл добавлен в репозиторий.yarnLockAutoReplace— автоматически заменяетyarn.lockпри каждом запуске задачи Gradle.
Чтобы использовать эти параметры, обновите файл скрипта сборки build.gradle.kts следующим образом:
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin::class.java) {
rootProject.the<YarnRootExtension>().yarnLockMismatchReport =
YarnLockMismatchReport.WARNING // NONE | FAIL
rootProject.the<YarnRootExtension>().reportNewYarnLock = false // true
rootProject.the<YarnRootExtension>().yarnLockAutoReplace = false // true
}
Добавление браузеров в качестве целевых платформ тестирования через свойства Gradle
Начиная с Kotlin 1.8.0, целевые платформы тестирования для разных браузеров можно задавать прямо в файле свойств Gradle. Это позволяет уменьшить размер скрипта сборки, поскольку больше не нужно перечислять все целевые платформы в build.gradle.kts.
С помощью этого свойства можно задать список браузеров для всех модулей, а затем добавить отдельные браузеры в скрипты сборки нужных модулей.
Например, следующая строка в файле свойств Gradle запускает тесты в Firefox и Safari для всех модулей:
kotlin.js.browser.karma.browsers=firefox,safari
Полный список допустимых значений свойства см. на GitHub.
Команда Kotlin выражает большую благодарность Мартинасy Петушке за реализацию этой возможности.
Новый способ добавления поддержки CSS в проект
В этом выпуске представлен новый способ добавления поддержки CSS в проект. Мы предполагаем, что это затронет многие проекты, поэтому не забудьте обновить файлы скриптов сборки Gradle, как описано ниже.
До Kotlin 1.8.0 для добавления поддержки CSS использовалось свойство cssSupport.enabled:
browser {
commonWebpackConfig {
cssSupport.enabled = true
}
}
Теперь следует использовать метод enabled.set() в блоке cssSupport {}:
browser {
commonWebpackConfig {
cssSupport {
enabled.set(true)
}
}
}
Gradle
Kotlin 1.8.0 полностью поддерживает Gradle версий 7.2 и 7.3. Вы также можете использовать версии Gradle вплоть до последнего выпуска, но имейте в виду, что при этом могут появиться предупреждения об устаревших функциях или некоторые новые функции Gradle могут не работать.
В этой версии появилось множество изменений:
Предоставление параметров компилятора Kotlin в виде ленивых свойств Gradle
Использование последней версии kotlin-stdlib в транзитивных зависимостях
Обязательная проверка совместимости целевых версий JVM связанных задач компиляции Kotlin и Java
Предоставление параметров компилятора Kotlin в виде ленивых свойств Gradle
Чтобы предоставить доступные параметры компилятора Kotlin в виде ленивых свойств Gradle и лучше интегрировать их в задачи Kotlin, мы внесли множество изменений:
-
У задач компиляции появился новый входной параметр
compilerOptions, похожий на существующийkotlinOptions, но использующийPropertyиз Gradle Properties API в качестве возвращаемого типа:tasks.named("compileKotlin", org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile::class.java) { compilerOptions { useK2.set(true) } } У задач Kotlin tools
KotlinJsDceиKotlinNativeLinkпоявился новый входной параметрtoolOptions, похожий на существующий входной параметрkotlinOptions.У новых входных параметров есть аннотация Gradle
@Nested. Каждое свойство внутри входных параметров имеет соответствующую аннотацию Gradle, например@Inputили@Internal.-
В артефакте API плагина Kotlin Gradle появились два новых интерфейса:
org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTaskс входным параметромcompilerOptionsи методомcompileOptions(). Все задачи компиляции Kotlin реализуют этот интерфейс.org.jetbrains.kotlin.gradle.tasks.KotlinToolTaskс входным параметромtoolOptionsи методомtoolOptions(). Все задачи Kotlin tools —KotlinJsDce,KotlinNativeLinkиKotlinNativeLinkArtifactTask— реализуют этот интерфейс.
-
В некоторых
compilerOptionsиспользуются новые типы вместо типаString:KotlinVersion(для входных параметровapiVersionиlanguageVersion)
Например, можно использовать
compilerOptions.jvmTarget.set(JvmTarget.JVM_11)вместоkotlinOptions.jvmTarget = "11".Типы
kotlinOptionsне изменились; внутри они преобразуются в типыcompilerOptions. API плагина Kotlin Gradle бинарно совместим с предыдущими выпусками. Однако в артефакте
kotlin-gradle-pluginесть некоторые изменения, нарушающие совместимость исходного кода и ABI. Большинство этих изменений связано с добавлением дополнительных обобщённых параметров для некоторых внутренних типов. Одно важное изменение: задачаKotlinNativeLinkбольше не наследует задачуAbstractKotlinNativeCompile.KotlinJsCompilerOptions.outputFileи связанные с ним параметрыKotlinJsOptions.outputFileобъявлены устаревшими. Вместо них используйте входной параметр задачиKotlin2JsCompile.outputFileProperty.
Ограничения
Вызов любого сеттера или геттера у kotlinOptions делегируется соответствующему свойству в compilerOptions. Это накладывает следующие ограничения:
compilerOptionsиkotlinOptionsнельзя изменять на этапе выполнения задачи (см. исключение в абзаце ниже).freeCompilerArgsвозвращает неизменяемыйList<String>, поэтому, например,kotlinOptions.freeCompilerArgs.remove("something")завершится ошибкой.
Некоторые плагины, в том числе kotlin-dsl и Android Gradle plugin (AGP) с включённым Jetpack Compose, пытаются изменить атрибут freeCompilerArgs на этапе выполнения задачи. В Kotlin 1.8.0 мы добавили для них обходное решение. Оно позволяет любому скрипту сборки или плагину изменять kotlinOptions.freeCompilerArgs на этапе выполнения, но при этом выводит предупреждение в журнал сборки. Чтобы отключить это предупреждение, используйте новое свойство Gradle kotlin.options.suppressFreeCompilerArgsModificationWarning=true. В Gradle планируют добавить исправления для плагина kotlin-dsl и AGP с включённым Jetpack Compose.
Повышение минимальных поддерживаемых версий
Начиная с Kotlin 1.8.0, минимальная поддерживаемая версия Gradle — 6.8.3, а минимальная поддерживаемая версия Android Gradle plugin — 4.1.3.
См. документацию о совместимости плагина Kotlin Gradle с доступными версиями Gradle
Возможность отключить резервную стратегию Kotlin daemon
Появилось новое свойство Gradle kotlin.daemon.useFallbackStrategy со значением по умолчанию true. Если его значение равно false, сборка завершается с ошибкой при проблемах с запуском или взаимодействием с daemon. Кроме того, в задачах компиляции Kotlin появилось новое свойство useDaemonFallbackStrategy, которое имеет приоритет над свойством Gradle, если используются оба. Если для выполнения компиляции недостаточно памяти, в журналах появится соответствующее сообщение.
Резервная стратегия компилятора Kotlin запускает компиляцию вне Kotlin daemon, если с daemon возникает сбой. Если Gradle daemon запущен, компилятор использует стратегию «In process». Если Gradle daemon не запущен, компилятор использует стратегию «Out of process». Подробнее см. в разделе Стратегия выполнения компилятора. Обратите внимание: незаметный переход на другую стратегию может потреблять много системных ресурсов или приводить к недетерминированным сборкам. Подробнее см. в задаче YouTrack.
Использование последней версии kotlin-stdlib в транзитивных зависимостях
Если вы явно укажете в зависимостях версию Kotlin 1.8.0 или выше, например: implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.0"), плагин Kotlin Gradle будет использовать эту версию Kotlin для транзитивных зависимостей kotlin-stdlib-jdk7 и kotlin-stdlib-jdk8. Это позволяет избежать дублирования классов из разных версий stdlib (подробнее о объединении kotlin-stdlib-jdk7 и kotlin-stdlib-jdk8 в kotlin-stdlib). Это поведение можно отключить с помощью свойства Gradle kotlin.stdlib.jdk.variants.version.alignment:
kotlin.stdlib.jdk.variants.version.alignment=false
Если у вас возникли проблемы с согласованием версий, согласуйте все версии с помощью Kotlin BOM, объявив зависимость от платформы kotlin-bom в скрипте сборки:
implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))
О других случаях и рекомендуемых решениях см. в документации.
Обязательная проверка целевых версий JVM связанных задач компиляции Kotlin и Java
Начиная с этого выпуска, значением по умолчанию для свойства kotlin.jvm.target.validation.mode для проектов с Gradle 8.0+ будет error (эта версия Gradle ещё не выпущена), и при несовместимости целевых версий JVM плагин завершит сборку с ошибкой.
Изменение значения по умолчанию с warning на error — подготовительный этап для плавного перехода на Gradle 8.0. Рекомендуем установить для этого свойства значение error и настроить набор инструментов или вручную согласовать версии JVM.
Подробнее о том, что может произойти, если не проверять совместимость целевых версий.
Разрешение транзитивных зависимостей плагинов Kotlin Gradle
В Kotlin 1.7.0 мы добавили поддержку вариантов плагинов Gradle. Из-за этих вариантов в classpath сборки могут присутствовать разные версии плагинов Kotlin Gradle, зависящие от разных версий некоторых зависимостей, обычно kotlin-gradle-plugin-api. Это может привести к проблеме разрешения зависимостей. В качестве обходного решения предлагаем использовать плагин kotlin-dsl.
Плагин kotlin-dsl в Gradle 7.6 зависит от плагина org.jetbrains.kotlin.plugin.sam.with.receiver:1.7.10, который зависит от kotlin-gradle-plugin-api:1.7.10. Если добавить плагин org.jetbrains.kotlin.gradle.jvm:1.8.0, эта транзитивная зависимость kotlin-gradle-plugin-api:1.7.10 может привести к ошибке разрешения зависимостей из-за несовпадения версий (1.8.0 и 1.7.10) и значений атрибута варианта org.gradle.plugin.api-version. В качестве обходного решения добавьте это ограничение, чтобы согласовать версии. Это решение может понадобиться до тех пор, пока мы не реализуем платформу согласования библиотек плагина Kotlin Gradle, которая включена в планы:
dependencies {
constraints {
implementation("org.jetbrains.kotlin:kotlin-sam-with-receiver:1.8.0")
}
}
Это ограничение принудительно задаёт версию org.jetbrains.kotlin:kotlin-sam-with-receiver:1.8.0 для транзитивных зависимостей в classpath сборки. Подробнее о похожем случае в системе отслеживания ошибок Gradle.
Устаревшие функции и удаления
В Kotlin 1.8.0 продолжается цикл устаревания следующих свойств и методов:
В примечаниях к Kotlin 1.7.0 было указано, что в задаче
KotlinCompileпо-прежнему было устаревшее свойство Kotlinclasspath, которое планировалось удалить в будущих выпусках. Теперь мы изменили уровень устаревания свойстваclasspathзадачиKotlinCompileнаerror. Во всех задачах компиляции входной параметрlibrariesиспользуется для списка библиотек, необходимых для компиляции.Мы удалили свойство
kapt.use.worker.api, позволявшее запускать kapt через Gradle Workers API. Начиная с Kotlin 1.3.70, kapt по умолчанию использует Gradle workers, и мы рекомендуем продолжать использовать этот способ.В Kotlin 1.7.0 мы объявили о начале цикла устаревания свойства
kotlin.compiler.execution.strategy. В этом выпуске мы удалили это свойство. Узнайте, как задать стратегию выполнения компилятора Kotlin другими способами.
Стандартная библиотека
Kotlin 1.8.0:
Обновляет целевую версию JVM для компиляции.
Стабилизирует несколько функций: преобразование TimeUnit между Java и Kotlin,
cbrt(), функции-расширения JavaOptionals.Предоставляет предварительную версию сравниваемых и вычитаемых
TimeMarks.Включает экспериментальные функции-расширения для
java.nio.file.path.Представляет улучшенную производительность kotlin-reflect.
Обновлённая целевая версия JVM для компиляции
В Kotlin 1.8.0 стандартные библиотеки (kotlin-stdlib, kotlin-reflect и kotlin-script-*) компилируются с целевой версией JVM 1.8. Ранее стандартные библиотеки компилировались с целевой версией JVM 1.6.
Kotlin 1.8.0 больше не поддерживает целевые версии JVM 1.6 и 1.7. Поэтому больше не нужно отдельно объявлять kotlin-stdlib-jdk7 и kotlin-stdlib-jdk8 в скриптах сборки, так как содержимое этих артефактов объединено с kotlin-stdlib.
Обратите внимание: смешивание разных версий артефактов stdlib может привести к дублированию или отсутствию классов. Чтобы этого избежать, плагин Kotlin Gradle может помочь вам согласовать версии stdlib.
cbrt()
Функция cbrt(), позволяющая вычислить действительный кубический корень из double или float, теперь имеет стабильный статус.
import kotlin.math.*
fun main() {
val num = 27
val negNum = -num
println("The cube root of ${num.toDouble()} is: " +
cbrt(num.toDouble()))
println("The cube root of ${negNum.toDouble()} is: " +
cbrt(negNum.toDouble()))
}
Преобразование TimeUnit между Java и Kotlin
Функции toTimeUnit() и toDurationUnit() в kotlin.time теперь имеют стабильный статус. Эти функции, представленные в Kotlin 1.6.0 в экспериментальном статусе, улучшают взаимодействие между Kotlin и Java. Теперь можно легко преобразовывать Java java.util.concurrent.TimeUnit в Kotlin kotlin.time.DurationUnit и обратно. Эти функции доступны только для JVM.
import kotlin.time.*
// For use from Java
fun wait(timeout: Long, unit: TimeUnit) {
val duration: Duration = timeout.toDuration(unit.toDurationUnit())
...
}
Сравниваемые и вычитаемые TimeMarks
До Kotlin 1.8.0, если требовалось вычислить разницу во времени между несколькими TimeMarks и текущим моментом, можно было вызвать elapsedNow() только для одной TimeMark за раз. Из-за этого было сложно сравнивать результаты: два вызова функции elapsedNow() нельзя было выполнить точно в один и тот же момент.
В Kotlin 1.8.0 эту проблему можно решить, вычитая и сравнивая TimeMarks, полученные из одного источника времени. Теперь можно создать экземпляр TimeMark, обозначающий текущий момент, и вычитать из него другие TimeMarks. Таким образом, результаты этих вычислений гарантированно будут относиться друг к другу.
import kotlin.time.*
fun main() {
//sampleStart
val timeSource = TimeSource.Monotonic
val mark1 = timeSource.markNow()
Thread.sleep(500) // Sleep 0.5 seconds
val mark2 = timeSource.markNow()
// Before 1.8.0
repeat(4) { n ->
val elapsed1 = mark1.elapsedNow()
val elapsed2 = mark2.elapsedNow()
// Difference between elapsed1 and elapsed2 can vary depending
// on how much time passes between the two elapsedNow() calls
println("Measurement 1.${n + 1}: elapsed1=$elapsed1, " +
"elapsed2=$elapsed2, diff=${elapsed1 - elapsed2}")
}
println()
// Since 1.8.0
repeat(4) { n ->
val mark3 = timeSource.markNow()
val elapsed1 = mark3 - mark1
val elapsed2 = mark3 - mark2
// Now the elapsed times are calculated relative to mark3,
// which is a fixed value
println("Measurement 2.${n + 1}: elapsed1=$elapsed1, " +
"elapsed2=$elapsed2, diff=${elapsed1 - elapsed2}")
}
// It's also possible to compare time marks with each other
// This is true, as mark2 was captured later than mark1
println(mark2 > mark1)
//sampleEnd
}
Эта новая возможность особенно полезна при вычислениях анимации, когда нужно вычислить разницу между несколькими TimeMarks, представляющими разные кадры, или сравнить их.
Рекурсивное копирование и удаление каталогов
Мы добавили две новые функции-расширения для java.nio.file.Path — copyToRecursively() и deleteRecursively(), которые позволяют рекурсивно выполнять следующие действия:
Копировать каталог и его содержимое в другое место.
Удалять каталог и его содержимое.
Эти функции могут быть очень полезны в процессе резервного копирования.
Обработка ошибок
С помощью copyToRecursively() можно определить, что должно произойти при возникновении исключения во время копирования, перегрузив лямбда-функцию onError:
sourceRoot.copyToRecursively(destinationRoot, followLinks = false,
onError = { source, target, exception ->
logger.logError(exception, "Failed to copy $source to $target")
OnErrorResult.TERMINATE
})
При использовании deleteRecursively(), если во время удаления файла или папки возникает исключение, этот файл или папка пропускается. После завершения удаления deleteRecursively() выбрасывает IOException, содержащее все возникшие исключения в качестве подавленных исключений.
Перезапись файлов
Если copyToRecursively() обнаружит, что файл уже существует в целевом каталоге, возникнет исключение. Чтобы вместо этого перезаписать файл, используйте перегрузку с аргументом overwrite и задайте ему значение true:
fun setUpEnvironment(projectDirectory: Path, fixtureName: String) {
fixturesRoot.resolve(COMMON_FIXTURE_NAME)
.copyToRecursively(projectDirectory, followLinks = false)
fixturesRoot.resolve(fixtureName)
.copyToRecursively(projectDirectory, followLinks = false,
overwrite = true) // patches the common fixture
}
Пользовательская операция копирования
Чтобы задать собственную логику копирования, используйте перегрузку с дополнительным аргументом copyAction. С помощью copyAction можно передать лямбда-функцию с нужными действиями, например:
sourceRoot.copyToRecursively(destinationRoot, followLinks = false) { source, target ->
if (source.name.startsWith(".")) {
CopyActionResult.SKIP_SUBTREE
} else {
source.copyToIgnoringExistingDirectory(target, followLinks = false)
CopyActionResult.CONTINUE
}
}
Подробнее об этих функциях-расширениях см. в справочнике API.
Функции-расширения Java Optionals
Функции-расширения, представленные в Kotlin 1.7.0, теперь имеют стабильный статус. Они упрощают работу с классами Optional в Java. Их можно использовать на JVM для извлечения и преобразования объектов Optional, а также для сокращения кода при работе с Java API. Подробнее см. в разделе Что нового в Kotlin 1.7.0.
Повышение производительности kotlin-reflect
Учитывая, что kotlin-reflect теперь компилируется с целевой версией JVM 1.8, мы перенесли механизм внутреннего кэширования на Java ClassValue. Раньше мы кэшировали только KClass, а теперь также кэшируем KType и KDeclarationContainer. Эти изменения значительно повысили производительность при вызове typeOf().
Обновления документации
В документации Kotlin появились заметные изменения:
Обновлённые и новые страницы
Обзор Gradle — узнайте, как настраивать и собирать проект Kotlin с помощью системы сборки Gradle, а также о доступных параметрах компилятора, компиляции и кэшах в плагине Kotlin Gradle.
Обработка null в Java и Kotlin — узнайте, чем отличаются подходы Java и Kotlin к обработке переменных, которые могут иметь значение null.
Руководство по Lincheck — узнайте, как настроить и использовать платформу Lincheck для тестирования параллельных алгоритмов на JVM.
Новые и обновлённые руководства
Начало работы с Gradle и Kotlin/JVM — создайте консольное приложение с помощью IntelliJ IDEA и Gradle.
Создание мультиплатформенного приложения с помощью Ktor и SQLDelight — создайте мобильное приложение для iOS и Android с помощью Kotlin Multiplatform Mobile.
Начало работы с Kotlin Multiplatform — узнайте о кроссплатформенной мобильной разработке на Kotlin и создайте приложение, работающее на Android и iOS.
Установка Kotlin 1.8.0
IntelliJ IDEA 2021.3, 2022.1 и 2022.2 автоматически предлагают обновить плагин Kotlin до версии 1.8.0. В IntelliJ IDEA 2022.3 версия 1.8.0 плагина Kotlin будет включена в одном из ближайших обновлений.
Для Android Studio Electric Eel (221) и Flamingo (222) версия 1.8.0 плагина Kotlin будет доступна в ближайших обновлениях Android Studio. Новый компилятор командной строки можно скачать на странице релиза на GitHub.
Руководство по совместимости с Kotlin 1.8.0
Kotlin 1.8.0 — это выпуск с новыми возможностями, поэтому он может содержать изменения, несовместимые с кодом, написанным для предыдущих версий языка. Подробный список этих изменений приведен в руководстве по совместимости с Kotlin 1.8.0.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew18.html