Что нового в Kotlin 2.3.0
Вышел Kotlin 2.3.0! Вот основные нововведения:
Kotlin/JVM: Поддержка Java 25.
Kotlin/Native: Улучшенное взаимодействие благодаря экспорту Swift, ускорение сборки задач выпуска, импорт библиотек C и Objective-C в статусе Beta.
Gradle: Совместимость с Gradle 9.0 и новый API для регистрации сгенерированных исходных файлов.
Компилятор Compose: Трассировки стека для минифицированных приложений Android.
Стандартная библиотека: Стабильные функции отслеживания времени, а также улучшенная генерация и разбор UUID.
Обзор обновлений также представлен в этом видео:
Поддержка IDE
Плагины Kotlin с поддержкой версии 2.3.0 входят в состав последних версий IntelliJ IDEA и Android Studio. Обновлять плагин Kotlin в IDE не нужно. Достаточно изменить версию Kotlin на 2.3.0 в сценариях сборки.
Подробности см. в разделе Обновление до новой версии.
Язык
В Kotlin 2.3.0 основное внимание уделено стабилизации функций, добавлен новый механизм обнаружения неиспользуемых возвращаемых значений и улучшено контекстно-зависимое разрешение.
Стабильные функции
В предыдущих версиях Kotlin были представлены несколько новых языковых функций в статусах Experimental и Beta. В Kotlin 2.3.0 следующие функции получили статус Stable:
Функции, включённые по умолчанию
В Kotlin 2.3.0 поддержка операторов return в телах-выражениях с явно указанными типами возвращаемого значения включена по умолчанию.
Проверка неиспользуемых возвращаемых значений
В Kotlin 2.3.0 добавлена проверка неиспользуемых возвращаемых значений, которая помогает не пропускать результаты. Она выдаёт предупреждение, если выражение возвращает значение, отличное от Unit или Nothing, и это значение не передаётся функции, не проверяется в условии и не используется иным образом.
Проверка помогает выявить ошибки, при которых вызов функции возвращает значимый результат, который незаметно отбрасывается. Это может привести к неожиданному поведению или проблемам, которые трудно отследить.
Рассмотрим следующий пример:
fun formatGreeting(name: String): String {
if (name.isBlank()) return "Hello, anonymous user!"
if (!name.contains(' ')) {
// The checker reports a warning that this result is ignored
"Hello, " + name.replaceFirstChar(Char::titlecase) + "!"
}
val (first, last) = name.split(' ')
return "Hello, $first! Or should I call you Dr. $last?"
}
В этом примере создаётся строка, которая нигде не используется, поэтому проверка сообщает о её неиспользованном результате.
Эта функция имеет статус Experimental. Чтобы включить её, добавьте в файл сборки следующий параметр компилятора:
kotlin {
compilerOptions {
freeCompilerArgs.add("-Xreturn-value-checker=check")
}
}
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xreturn-value-checker=check</arg>
</args>
</configuration>
</plugin>
</plugins>
</build>
При использовании этого параметра проверка сообщает только о неиспользуемых результатах выражений с соответствующей пометкой, например большинства функций стандартной библиотеки Kotlin.
Чтобы пометить свои функции, используйте аннотацию @MustUseReturnValues, указав область, в которой проверка должна сообщать о неиспользуемых возвращаемых значениях.
Например, можно пометить целый файл:
// Marks all functions and classes in this file so the checker reports unused return values @file:MustUseReturnValues package my.project fun someFunction(): String
Также можно пометить определённый класс:
// Marks all functions in this class so the checker reports unused return values
@MustUseReturnValues
class Greeter {
fun greet(name: String): String = "Hello, $name"
}
fun someFunction(): Int = ...
Кроме того, можно пометить весь проект, добавив в файл сборки следующий параметр компилятора:
kotlin {
compilerOptions {
freeCompilerArgs.add("-Xreturn-value-checker=full")
}
}
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xreturn-value-checker=full</arg>
</args>
</configuration>
</plugin>
</plugins>
</build>
При этой настройке Kotlin автоматически обрабатывает скомпилированные файлы так, как если бы они были аннотированы @MustUseReturnValues, а проверка сообщает обо всех возвращаемых значениях функций проекта.
Чтобы отключить предупреждения для определённых функций, пометьте их аннотацией @IgnorableReturnValue. Используйте её для функций, результаты которых обычно и ожидаемо игнорируются, например MutableList.add:
@IgnorableReturnValue
fun <T> MutableList<T>.addAndIgnoreResult(element: T): Boolean {
return add(element)
}
Можно отключить предупреждение, не помечая саму функцию как допускающую игнорирование результата. Для этого присвойте результат специальной безымянной переменной с подчёркиванием (_):
// Non-ignorable function
fun computeValue(): Int = 42
fun main() {
// Reports a warning: result is ignored
computeValue()
// Suppresses the warning only at this call site with a special unused variable
val _ = computeValue()
}
Дополнительную информацию см. в KEEP этой функции.
Будем рады вашим отзывам в YouTrack.
Явные поля хранения
В Kotlin 2.3.0 представлены явные поля хранения — новый синтаксис для явного объявления поля, в котором хранится значение свойства, в отличие от существующих неявных полей хранения.
Обзор этой функции представлен в этом видео:
Новый явный синтаксис упрощает распространённый шаблон с резервным свойством, при котором внутренний тип свойства отличается от типа в его открытом API. Например, можно использовать ArrayList, предоставляя доступ к нему как к доступному только для чтения List или MutableList. Ранее для этого требовалось дополнительное приватное свойство.
При использовании явных полей хранения тип реализации field задаётся непосредственно в области видимости свойства. Это избавляет от необходимости создавать отдельное приватное свойство и позволяет компилятору автоматически выполнять интеллектуальное приведение к типу поля хранения в той же приватной области видимости.
До:
private val _city = MutableStateFlow<String>("")
val city: StateFlow<String> get() = _city
fun updateCity(newCity: String) {
_city.value = newCity
}
После:
val city: StateFlow<String>
field = MutableStateFlow("")
fun updateCity(newCity: String) {
// Smart casting works automatically
city.value = newCity
}
Эта функция имеет статус Experimental. Чтобы включить её, добавьте в файл сборки следующий параметр компилятора:
kotlin {
compilerOptions {
freeCompilerArgs.add("-Xexplicit-backing-fields")
}
}
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xexplicit-backing-fields</arg>
</args>
</configuration>
</plugin>
</plugins>
</build>
Дополнительную информацию см. в KEEP этой функции.
Будем рады вашим отзывам в YouTrack.
Изменения контекстно-зависимого разрешения
Контекстно-зависимое разрешение по-прежнему имеет статус Experimental, но мы постоянно улучшаем эту функцию с учётом отзывов пользователей:
Запечатанные и охватывающие суперклассы текущего типа теперь считаются частью контекстной области поиска. Другие области суперклассов не рассматриваются. Обоснование и примеры см. в задаче KT-77823 в YouTrack.
Если используются операторы типов и равенства, компилятор теперь выдаёт предупреждение, когда контекстно-зависимое разрешение приводит к неоднозначности. Это может произойти, например, при импорте конфликтующего объявления класса. Обоснование и примеры см. в задаче KT-77821 в YouTrack.
Полный текст текущего предложения см. в KEEP.
Kotlin/JVM: поддержка Java 25
Начиная с Kotlin 2.3.0 компилятор может генерировать классы, содержащие байт-код Java 25.
Kotlin/Native
В Kotlin 2.3.0 улучшена поддержка экспорта Swift и импорта библиотек C и Objective-C, а также ускорена сборка задач выпуска.
Улучшенное взаимодействие благодаря экспорту Swift
В Kotlin 2.3.0 продолжено улучшение взаимодействия Kotlin со Swift посредством экспорта Swift: добавлена поддержка нативных классов enum и параметров функций с переменным числом аргументов.
Ранее перечисления Kotlin экспортировались как обычные классы Swift. Теперь используется прямое сопоставление, и можно применять стандартные нативные перечисления Swift. Например:
// Kotlin
enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}
val color = Color.RED
// Swift
public enum Color: Swift.CaseIterable, Swift.LosslessStringConvertible, Swift.RawRepresentable {
case RED, GREEN, BLUE
var rgb: Int { get }
}
Кроме того, функции Kotlin с vararg теперь напрямую сопоставляются с параметрами функций Swift с переменным числом аргументов.
Такие функции позволяют передавать переменное количество аргументов. Это полезно, когда число аргументов заранее неизвестно или когда нужно создать или передать коллекцию, не указывая её тип. Например:
// Kotlin fun log(vararg messages: String)
// Swift public func log(messages: Swift.String...)
Импорт библиотек C и Objective-C имеет статус Beta
Поддержка импорта библиотек C и Objective-C в проекты Kotlin/Native имеет статус Beta.
Полная совместимость с разными версиями Kotlin, зависимостями и Xcode пока не гарантируется, однако теперь компилятор выдаёт более точные диагностические сообщения при проблемах бинарной совместимости.
Импорт ещё не является стабильным, поэтому при использовании библиотек C и Objective-C в проекте по-прежнему требуется аннотация для подтверждения участия @ExperimentalForeignApi в некоторых случаях, связанных с взаимодействием с C и Objective-C, в том числе:
Некоторые API пакета
kotlinx.cinterop.*, необходимые при работе с нативными библиотеками или памятью.Все объявления в нативных библиотеках, кроме библиотек платформы.
Чтобы обеспечить совместимость и избавить вас от необходимости изменять исходный код, новое состояние стабильности не отражено в названии аннотации.
Дополнительную информацию см. в разделе Стабильность импорта библиотек C и Objective-C.
Явные имена по умолчанию в типах блоков заголовков Objective-C
Явные имена параметров в типах функций Kotlin, представленные в Kotlin 2.2.20, теперь используются по умолчанию в заголовках Objective-C, экспортируемых из проектов Kotlin/Native. Эти имена параметров улучшают подсказки автодополнения в Xcode и помогают избежать предупреждений Clang.
Рассмотрим следующий код Kotlin:
// Kotlin:
fun greetUser(block: (name: String) -> Unit) = block("John")
Kotlin передаёт имена параметров из типов функций Kotlin типам блоков Objective-C, благодаря чему Xcode может использовать их в подсказках:
// Objective-C:
greetUserBlock:^(NSString *name) {
// ...
};
Если возникнут проблемы, явные имена параметров можно отключить. Для этого добавьте следующий параметр бинарного файла в файл gradle.properties:
kotlin.native.binary.objcExportBlockExplicitParameterNames=false
Сообщайте о любых проблемах в YouTrack.
Ускорение сборки задач выпуска
В Kotlin/Native в версии 2.3.0 внесено несколько улучшений производительности. Благодаря им ускорилась сборка задач выпуска, таких как linkRelease*, например linkReleaseFrameworkIosArm64.
Согласно нашим тестам производительности, сборка выпуска может быть быстрее до 40%, в зависимости от размера проекта. Улучшения особенно заметны в проектах Kotlin Multiplatform для iOS.
Дополнительные советы по ускорению компиляции проекта см. в документации.
Изменения поддержки целевых платформ Apple
В Kotlin 2.3.0 повышены минимальные поддерживаемые версии целевых платформ Apple:
Для iOS и tvOS — с 12.0 до 14.0.
Для watchOS — с 5.0 до 7.0.
Согласно общедоступным данным, использование старых версий уже крайне ограничено. Это изменение упрощает обслуживание целевых платформ Apple и открывает возможность добавить поддержку Mac Catalyst в Kotlin/Native.
Если в проекте необходимо сохранить поддержку старых версий, добавьте в файл сборки следующие строки:
kotlin {
targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>().configureEach {
binaries.configureEach {
freeCompilerArgs += "-Xoverride-konan-properties=minVersion.ios=12.0"
freeCompilerArgs += "-Xoverride-konan-properties=minVersion.tvos=12.0"
}
}
}
Обратите внимание, что такая конфигурация не гарантирует успешную компиляцию и может привести к сбоям приложения во время сборки или выполнения.
В этом выпуске также сделан следующий шаг в цикле прекращения поддержки целевых платформ Apple на базе чипов Intel.
Начиная с Kotlin 2.3.0 целевые платформы macosX64, iosX64, tvosX64 и watchosX64 переводятся на третий уровень поддержки. Это означает, что их тестирование в CI не гарантируется, а совместимость исходного и бинарного кода между разными версиями компилятора может не обеспечиваться. В Kotlin 2.4.0 мы планируем полностью удалить поддержку целевых платформ Apple x86_64.
Дополнительную информацию см. в разделе Поддержка целевых платформ Kotlin/Native.
Kotlin/Wasm
В Kotlin 2.3.0 для целевых платформ Kotlin/Wasm по умолчанию включены полностью квалифицированные имена и новое предложение по обработке исключений для целевой платформы wasmWasi, а также добавлено компактное хранение символов Latin-1.
Полностью квалифицированные имена включены по умолчанию
В целевых платформах Kotlin/Wasm полностью квалифицированные имена (FQN) не были включены по умолчанию во время выполнения. Чтобы использовать FQN, требовалось вручную включить поддержку свойства KClass.qualifiedName.
Было доступно только имя класса без пакета, что создавало проблемы для кода, перенесённого с JVM на целевые платформы Wasm, и библиотек, которым во время выполнения нужны полностью квалифицированные имена.
В Kotlin 2.3.0 свойство KClass.qualifiedName включено по умолчанию для целевых платформ Kotlin/Wasm. Это означает, что FQN доступны во время выполнения без дополнительной настройки.
Включение FQN по умолчанию повышает переносимость кода и делает ошибки времени выполнения информативнее, поскольку отображается полностью квалифицированное имя.
Это изменение не увеличивает размер скомпилированного двоичного файла Wasm благодаря оптимизациям компилятора, сокращающим метаданные за счёт компактного хранения строковых литералов Latin-1.
Компактное хранение символов Latin-1
Ранее Kotlin/Wasm хранил данные строковых литералов без изменений, то есть каждый символ кодировался в UTF-16. Это было неэффективно для текста, содержащего только или преимущественно символы Latin-1.
Начиная с Kotlin 2.3.0 компилятор Kotlin/Wasm хранит строковые литералы, содержащие только символы Latin-1, в формате UTF-8.
Как показали эксперименты с приложением KotlinConf JetBrains, эта оптимизация значительно сокращает объём метаданных. Результаты:
Двоичные файлы Wasm до 13% меньше по сравнению со сборками без этой оптимизации.
Двоичные файлы Wasm до 8% меньше даже при включённых полностью квалифицированных именах по сравнению с предыдущими версиями, в которых они не сохранялись.
Компактное хранение важно для веб-сред, где имеют значение время загрузки и запуска. Кроме того, эта оптимизация устраняет ограничение на размер, которое ранее мешало хранить полностью квалифицированные имена классов и включать KClass.qualifiedName по умолчанию.
Это изменение включено по умолчанию, дополнительных действий не требуется.
Новое предложение по обработке исключений включено по умолчанию для wasmWasi
Ранее Kotlin/Wasm использовал устаревшее предложение по обработке исключений для всех целевых платформ, в том числе wasmWasi. Однако большинство автономных виртуальных машин WebAssembly (VM) переходят на новую версию предложения по обработке исключений.
Начиная с Kotlin 2.3.0 новое предложение WebAssembly по обработке исключений включено по умолчанию для целевой платформы wasmWasi, что обеспечивает лучшую совместимость с современными средами выполнения WebAssembly.
Для целевой платформы wasmWasi это изменение безопасно внести заранее, поскольку приложения для неё обычно работают в менее разнообразных средах выполнения (часто на одной конкретной VM), которая, как правило, контролируется пользователем. Это снижает риск проблем с совместимостью.
Для целевой платформы wasmJs новое предложение по обработке исключений по умолчанию остаётся выключенным. Его можно включить вручную с помощью параметра компилятора -Xwasm-use-new-exception-proposal.
Kotlin/JS
Kotlin 2.3.0 добавляет экспериментальную поддержку экспорта suspend-функций в JavaScript и типа BigInt64Array для представления типа LongArray в Kotlin.
В этом выпуске вы можете получать доступ к companion-объектам внутри интерфейсов единообразным способом, использовать аннотацию @JsStatic в интерфейсах с companion-объектами, аннотацию @JsQualifier для отдельных функций и классов, а также использовать экспорт по умолчанию с помощью новой аннотации @JsExport.Default.
Новый способ экспорта suspend-функций с помощью JsExport
Ранее аннотация @JsExport не позволяла экспортировать suspend-функции (или классы и интерфейсы, содержащие такие функции) в JavaScript. Приходилось вручную создавать обёртку для каждой suspend-функции, что было неудобно и могло приводить к ошибкам.
Начиная с Kotlin 2.3.0, suspend-функции можно напрямую экспортировать в JavaScript с помощью аннотации @JsExport.
Экспорт suspend-функций позволяет сократить шаблонный код и улучшает взаимодействие между Kotlin/JS и JavaScript/TypeScript (JS/TS). Теперь асинхронные функции Kotlin можно вызывать непосредственно из JS/TS без дополнительного кода.
Чтобы включить эту функцию, добавьте следующий параметр компилятора в файл build.gradle.kts:
kotlin {
compilerOptions {
freeCompilerArgs.add("-Xenable-suspend-function-exporting")
}
}
После включения этой функции классы и функции с аннотацией @JsExport могут содержать suspend-функции без дополнительных обёрток.
Их можно использовать как обычные асинхронные функции JavaScript, а также переопределять в виде асинхронной функции:
@JsExport
open class Foo {
suspend fun foo() = "Foo"
}
class Bar extends Foo {
override async foo(): Promise<string> {
return "Bar"
}
}
Эта функция имеет статус экспериментальной. Будем признательны за ваши отзывы в нашем трекере задач YouTrack.
Использование типа BigInt64Array для представления типа LongArray в Kotlin
Ранее Kotlin/JS представлял LongArray в виде значения JavaScript типа Array<bigint>. Этот подход работал, но был неидеален для взаимодействия с API JavaScript, ожидающими типизированные массивы.
Начиная с этого выпуска, Kotlin/JS использует встроенный тип JavaScript BigInt64Array для представления значений LongArray в Kotlin при компиляции в JavaScript.
Использование BigInt64Array упрощает взаимодействие с API JavaScript, использующими типизированные массивы. Кроме того, благодаря этому API, принимающие или возвращающие LongArray, можно естественнее экспортировать из Kotlin в JavaScript.
Чтобы включить эту функцию, добавьте следующий параметр компилятора в файл build.gradle.kts:
kotlin {
js {
// ...
compilerOptions {
freeCompilerArgs.add("-Xes-long-as-bigint")
}
}
}
Эта функция имеет статус экспериментальной. Будем признательны за ваши отзывы в нашем трекере задач YouTrack.
Единообразный доступ к companion-объектам во всех модульных системах JS
Ранее при экспорте интерфейса Kotlin с companion-объектом в JavaScript/TypeScript с помощью аннотации @JsExport его использование в TypeScript отличалось для ES-модулей и других модульных систем.
В результате способ использования результата на стороне TypeScript приходилось менять в зависимости от модульной системы.
Рассмотрим следующий код Kotlin:
@JsExport
interface Foo {
companion object {
fun bar() = "OK"
}
}
Вызов требовалось выполнять по-разному в зависимости от модульной системы:
// Worked for CommonJS, AMD, UMD, and no modules Foo.bar() // Worked for ES modules Foo.getInstance().bar()
В этом выпуске Kotlin унифицирует экспорт companion-объектов для всех модульных систем JavaScript.
Теперь во всех модульных системах (ES modules, CommonJS, AMD, UMD и без модулей) доступ к companion-объектам внутри интерфейсов осуществляется одинаково (как и к companion-объектам в классах):
// Works for all module systems Foo.Companion.bar()
Это улучшение также исправляет взаимодействие с коллекциями. Ранее доступ к фабричным функциям коллекций зависел от модульной системы:
// Worked for CommonJS, AMD, UMD, and no modules KtList.fromJsArray([1, 2, 3]) // Worked for ES modules KtList.getInstance().fromJsArray([1, 2, 3])
Теперь доступ к фабричным функциям коллекций осуществляется одинаково во всех модульных системах:
// Works for all module systems KtList.fromJsArray([1, 2, 3])
Это изменение устраняет несогласованное поведение разных модульных систем и предотвращает ошибки и проблемы взаимодействия.
Эта функция включена по умолчанию.
Поддержка аннотаций @JsStatic в интерфейсах с companion-объектами
Ранее аннотацию @JsStatic нельзя было использовать внутри экспортируемых интерфейсов с companion-объектами.
Например, следующий код приводил бы к ошибке, поскольку аннотацию @JsStatic можно применять только к членам companion-объектов классов:
@JsExport
interface Foo {
companion object {
@JsStatic // Error
fun bar() = "OK"
}
}
В этом случае приходилось убирать аннотацию @JsStatic и обращаться к companion-объекту из JavaScript (JS) следующим образом:
// For all module systems Foo.Companion.bar()
Теперь аннотация @JsStatic поддерживается в интерфейсах с companion-объектами. Её можно использовать с такими companion-объектами и вызывать функцию напрямую из JS, как и в случае с классами:
// For all module systems Foo.bar()
Это изменение упрощает использование API в JS, позволяет создавать статические фабричные методы в интерфейсах и устраняет различия между классами и интерфейсами.
Эта функция включена по умолчанию.
Аннотацию @JsQualifier можно использовать для отдельных функций и классов
Ранее аннотацию @JsQualifier можно было применять только на уровне файла, поэтому все внешние объявления JavaScript (JS) приходилось размещать в отдельных файлах.
Начиная с Kotlin 2.3.0, аннотацию @JsQualifier можно применять непосредственно к отдельным функциям и классам, как и аннотации @JsModule и @JsNonModule.
Например, теперь код следующей внешней функции можно разместить в том же файле, что и обычные объявления Kotlin:
@JsQualifier("jsPackage")
private external fun jsFun()
Это изменение упрощает взаимодействие Kotlin/JS, помогает поддерживать более чистую структуру проекта и обеспечивает согласованность Kotlin/JS с тем, как другие платформы обрабатывают внешние объявления.
Эта функция включена по умолчанию.
Поддержка экспорта по умолчанию в JavaScript
Ранее Kotlin/JS не мог создавать экспорт по умолчанию в JavaScript из кода Kotlin. Вместо этого Kotlin/JS создавал только именованные экспорты, например:
export { SomeDeclaration };
Если требовался экспорт по умолчанию, приходилось использовать обходные решения внутри компилятора, например указывать аннотацию @JsName с аргументом default и пробелом:
@JsExport
@JsName("default ")
class SomeDeclaration
Теперь Kotlin/JS поддерживает экспорт по умолчанию напрямую с помощью новой аннотации:
@JsExport.Default
При применении этой аннотации к объявлению Kotlin (классу, объекту, функции или свойству) сгенерированный JavaScript автоматически включает инструкцию export default для ES-модулей:
export default HelloWorker;
Это изменение позволяет коду Kotlin соответствовать соглашениям JavaScript и особенно важно для таких платформ, как Cloudflare Workers, и таких фреймворков, как React.lazy.
Эта функция включена по умолчанию. Достаточно использовать аннотацию @JsExport.Default.
Gradle
Kotlin 2.3.0 полностью совместим с Gradle версий от 7.6.3 до 9.0.0. Также можно использовать более поздние версии Gradle, вплоть до последнего выпуска. Однако учтите, что это может привести к предупреждениям об устаревших функциях, а некоторые новые функции Gradle могут не работать.
Кроме того, минимальная поддерживаемая версия Android Gradle plugin теперь составляет 8.2.2, а максимальная — 8.13.0.
В Kotlin 2.3.0 также появился новый API для регистрации сгенерированных исходных файлов в проектах Gradle.
Новый API для регистрации сгенерированных исходных файлов в проектах Gradle
В Kotlin 2.3.0 появился новый экспериментальный API в интерфейсе KotlinSourceSet, который можно использовать для регистрации сгенерированных исходных файлов в проектах Gradle.
Этот новый API упрощает работу: он помогает IDE отличать сгенерированный код от обычных исходных файлов. API позволяет IDE по-разному выделять сгенерированный код в интерфейсе и запускать задачи генерации при импорте проекта. Сейчас мы работаем над добавлением этой поддержки в IntelliJ IDEA. Этот API также особенно полезен для сторонних плагинов и инструментов, генерирующих код, например KSP (Kotlin Symbol Processing).
Подробнее см. в разделе Регистрация сгенерированных исходных файлов.
Стандартная библиотека
В Kotlin 2.3.0 стабилизирована новая функциональность отслеживания времени — kotlin.time.Clock и kotlin.time.Instant, — а также добавлено несколько улучшений экспериментального API UUID.
Улучшенная генерация и разбор UUID
В Kotlin 2.3.0 добавлено несколько улучшений API UUID, в том числе:
Поддержка UUID в стандартной библиотеке имеет статус экспериментальной, но её планируется стабилизировать в будущем. Чтобы включить эту функцию, используйте аннотацию @OptIn(ExperimentalUuidApi::class) или добавьте следующий параметр компилятора в файл сборки:
kotlin {
compilerOptions {
freeCompilerArgs.add("-opt-in=kotlin.uuid.ExperimentalUuidApi")
}
}
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-opt-in=kotlin.uuid.ExperimentalUuidApi</arg>
</args>
</configuration>
</plugin>
</plugins>
</build>
Будем признательны за ваши отзывы в YouTrack или в соответствующем канале Slack.
Поддержка возврата null при разборе некорректных UUID
В Kotlin 2.3.0 появились новые функции для создания экземпляра Uuid из строки. Если строка не является корректным UUID, эти функции возвращают null, а не выбрасывают исключение.
К ним относятся следующие функции:
Uuid.parseOrNull()— разбирает UUID в шестнадцатеричном формате с дефисами или без них.Uuid.parseHexDashOrNull()— разбирает UUID только в шестнадцатеричном формате с дефисами и в противном случае возвращаетnull.Uuid.parseHexOrNull()— разбирает UUID только в обычном шестнадцатеричном формате и в противном случае возвращаетnull.
Пример:
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
@OptIn(ExperimentalUuidApi::class)
fun main() {
val valid = Uuid.parseOrNull("550e8400-e29b-41d4-a716-446655440000")
println(valid)
// 550e8400-e29b-41d4-a716-446655440000
val invalid = Uuid.parseOrNull("not-a-uuid")
println(invalid)
// null
val hexDashValid = Uuid.parseHexDashOrNull("550e8400-e29b-41d4-a716-446655440000")
println(hexDashValid)
// 550e8400-e29b-41d4-a716-446655440000
val hexDashInvalid = Uuid.parseHexDashOrNull("550e8400e29b41d4a716446655440000")
println(hexDashInvalid)
// null
}
Новые функции для генерации UUID версий 4 и 7
В Kotlin 2.3.0 появились две новые функции для генерации UUID: Uuid.generateV4() и Uuid.generateV7().
Используйте функцию Uuid.generateV4() для генерации UUID версии 4, а функцию Uuid.generateV7() — для генерации UUID версии 7.
Пример:
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
@OptIn(ExperimentalUuidApi::class)
fun main() {
// Generates a v4 UUID
val v4 = Uuid.generateV4()
println(v4)
// Generates a v7 UUID
val v7 = Uuid.generateV7()
println(v7)
// Generates a v4 UUID
val random = Uuid.random()
println(random)
}
Поддержка генерации UUID версии 7 для заданных временных меток
В Kotlin 2.3.0 появилась новая функция Uuid.generateV7NonMonotonicAt(), которую можно использовать для генерации UUID версии 7 для определённого момента времени.
Используйте эту функцию, если вам нужны идентификаторы, привязанные к известной временной метке, например при восстановлении идентификаторов событий или создании записей базы данных, отражающих время исходного события.
Например, чтобы создать UUID версии 7 для конкретного момента времени, используйте следующий код:
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
import kotlin.time.ExperimentalTime
import kotlin.time.Instant
@OptIn(ExperimentalUuidApi::class, ExperimentalTime::class)
fun main() {
val timestamp = Instant.fromEpochMilliseconds(1577836800000) // 2020-01-01T00:00:00Z
// Generates a v7 UUID for the specified timestamp (without monotonicity guarantees)
val v7AtTimestamp = Uuid.generateV7NonMonotonicAt(timestamp)
println(v7AtTimestamp)
}
Компилятор Compose: трассировки стека для минифицированных приложений Android
Начиная с Kotlin 2.3.0, компилятор создаёт таблицы соответствий ProGuard для трассировок стека Compose, если приложения минифицируются с помощью R8. Это расширяет экспериментальную функцию трассировок стека, ранее доступную только в отлаживаемых вариантах сборки.
Трассировки стека в варианте release содержат ключи групп, по которым можно идентифицировать composable-функции в минифицированных приложениях без затрат на запись информации об исходном коде во время выполнения. Для трассировок стека с ключами групп требуется, чтобы приложение собиралось с Compose runtime версии 1.10 или новее.
Чтобы включить трассировки стека с ключами групп, добавьте следующую строку перед инициализацией любого содержимого @Composable:
Composer.setDiagnosticStackTraceMode(ComposeStackTraceMode.GroupKeys)
Если эти трассировки стека включены, Compose runtime добавит собственную трассировку стека после перехвата сбоя во время композиции, измерения или отрисовки, даже если приложение минифицировано:
java.lang.IllegalStateException: <message>
at <original trace>
Suppressed: androidx.compose.runtime.DiagnosticComposeException: Composition stack when thrown:
at $$compose.m$123(SourceFile:1)
at $$compose.m$234(SourceFile:1)
...
Трассировки стека, создаваемые Jetpack Compose 1.10 в этом режиме, содержат только ключи групп, которые ещё требуется деобфусцировать. Это исправлено в выпуске Kotlin 2.3.0 с помощью плагина Compose Compiler Gradle: теперь он добавляет записи ключей групп в файлы таблиц соответствий ProGuard, созданные R8. Если вы столкнётесь с новыми предупреждениями в случаях, когда компилятору не удаётся создать таблицы соответствий для некоторых функций, сообщите об этом в Google IssueTracker.
По умолчанию задачи Gradle для файлов таблиц соответствий выполняются независимо от того, включены ли трассировки. Если они вызывают проблемы при сборке, эту функцию можно полностью отключить. Добавьте следующее свойство в блок composeCompiler {} конфигурации Gradle:
composeCompiler {
includeComposeMappingFile.set(false)
}
Сообщайте о любых возникших проблемах в Google IssueTracker.
Несовместимые изменения и устаревшие функции
В этом разделе описаны важные несовместимые изменения и устаревшие функции. Полный обзор см. в руководстве по совместимости.
Начиная с Kotlin 2.3.0, компилятор больше не поддерживает
-language-version=1.8. Кроме того, на платформах, отличных от JVM, не поддерживается-language-version=1.9.-
Наборы языковых функций версий ниже 2.0 (за исключением версии 1.9 для платформы JVM) не поддерживаются, однако сам язык полностью сохраняет обратную совместимость с Kotlin 1.0.
Если в проекте Gradle используются плагины
kotlin-dslиkotlin("jvm"), вы можете увидеть предупреждение Gradle о неподдерживаемой версии плагина Kotlin. Рекомендации по переносу см. в нашем руководстве по совместимости. В Kotlin Multiplatform поддержка целевой платформы Android теперь доступна через плагин
com.android.kotlin.multiplatform.libraryот Google. Перенесите проекты с целевыми платформами Android на новый плагин и переименуйте блокиandroidTargetвandroid.Если продолжить использовать плагин Kotlin Multiplatform Gradle для целевых платформ Android с Android Gradle plugin (AGP) версии 9.0.0 или новее, при использовании блока
androidTargetвозникнет ошибка конфигурации и будут выведены диагностические сообщения с рекомендациями по переносу. Этой ошибки можно избежать, используя AGP 8.x и обновившись до Kotlin 2.3.10, либо перейдя на плагин Google для целевых платформ Android.В AGP 9.0.0 встроена поддержка Kotlin. Начиная с Kotlin 2.3.0, при использовании этой версии AGP с плагином
kotlin-androidвозникнет ошибка конфигурации, поскольку этот плагин больше не нужен. Для упрощения переноса доступны новые диагностические сообщения. При использовании более старых версий AGP выводится предупреждение об устаревании.Поддержка системы сборки Ant прекращена.
Обновления документации
Документация по Kotlin Multiplatform перенесена на kotlinlang.org. Теперь можно переключаться между документацией по Kotlin и KMP в одном месте. Мы также обновили оглавление руководства по языку и добавили новую навигацию.
Другие заметные изменения с момента последнего выпуска Kotlin:
Обзор KMP — познакомьтесь с экосистемой Kotlin Multiplatform на одной странице.
Краткое руководство по Kotlin Multiplatform — узнайте, как настроить среду с помощью плагина KMP для IDE.
Что нового в Compose Multiplatform 1.9.3 — ознакомьтесь с основными нововведениями последнего выпуска.
Начало работы с Kotlin/JS — создайте веб-приложение для браузера с помощью Kotlin/JavaScript.
Классы — изучите основы и рекомендации по использованию классов в Kotlin.
Расширения — узнайте, как расширять классы и интерфейсы в Kotlin.
Основы корутин — познакомьтесь с основными понятиями, связанными с корутинами, и узнайте, как создать свои первые корутины.
Отмена и тайм-ауты — узнайте, как работает отмена корутин и как обеспечить реакцию корутин на отмену.
Библиотеки Kotlin/Native — узнайте, как создавать артефакты библиотек
klib.Обзор Kotlin Notebook — создавайте интерактивные документы-блокноты с помощью плагина Kotlin Notebook.
Добавление Kotlin в проект Java — настройте проект Java для совместного использования Kotlin и Java.
Тестирование кода Java с помощью Kotlin — протестируйте проект, сочетающий Java и Kotlin, с помощью JUnit.
Новая страница с примерами использования — узнайте, как разные компании применяют Kotlin.
Как обновиться до Kotlin 2.3.0
Плагин Kotlin распространяется в составе IntelliJ IDEA и Android Studio.
Чтобы обновиться до новой версии Kotlin, измените версию Kotlin в скриптах сборки на 2.3.0.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew23.html