Spec-Zone.ru › Kotlin 1.6

Что нового в Kotlin 1.6.0

Дата выхода: 16 ноября 2021 года

Kotlin 1.6.0 включает новые возможности языка, оптимизации и улучшения существующих функций, а также множество улучшений стандартной библиотеки Kotlin.

Обзор изменений также доступен в посте о выпуске.

Язык

Kotlin 1.6.0 включает стабилизацию нескольких возможностей языка, представленных в предварительной версии в предыдущем релизе 1.5.30:

  • Стабильные исчерпывающие выражения when для перечислений, sealed классов и булевых значений

  • Стабильные приостанавливаемые функции как типы-супертипы

  • Стабильные преобразования suspend

  • Стабильное создание экземпляров аннотационных классов

Также в релизе присутствуют различные улучшения вывода типов и поддержка аннотаций на параметрах типов классов:

  • Улучшенный вывод типов для рекурсивных обобщенных типов

  • Изменения в выводе типов для билдеров

  • Поддержка аннотаций на параметрах типов классов

Стабильные исчерпывающие выражения `when` для перечислений, sealed классов и булевых значений

Выражение исчерпывающее when содержит ветви для всех возможных типов или значений его объекта, или для некоторых типов плюс else ветвь. Оно охватывает все возможные случаи, что повышает безопасность вашего кода.

Вскоре мы запретим неисчерпывающие when выражения, чтобы обеспечить согласованность поведения с when выражениями. Для плавной миграции в Kotlin 1.6.0 генерируются предупреждения о неисчерпывающих when выражениях с объектом-перечислением, sealed классом или булевым значением. Эти предупреждения станут ошибками в будущих версиях.

sealed class Contact {
    data class PhoneCall(val number: String) : Contact()
    data class TextMessage(val number: String) : Contact()
}

fun Contact.messageCost(): Int =
    when(this) { // Error: 'when' expression must be exhaustive
        is Contact.PhoneCall -> 42
    }

fun sendMessage(contact: Contact, message: String) {
    // Starting with 1.6.0

    // Warning: Non exhaustive 'when' statements on Boolean will be
    // prohibited in 1.7, add 'false' branch or 'else' branch instead 
    when(message.isEmpty()) {
        true -> return
    }
    // Warning: Non exhaustive 'when' statements on sealed class/interface will be
    // prohibited in 1.7, add 'is TextMessage' branch or 'else' branch instead
    when(contact) {
        is Contact.PhoneCall -> TODO()
    }
}

См. этот тикет YouTrack для более подробного объяснения изменения и его последствий.

Стабильные приостанавливаемые функции как типы-супертипы

Реализация приостанавливаемых функциональных типов стала стабильной в Kotlin 1.6.0. Предварительный просмотр был доступен в 1.5.30.

Это полезно при проектировании API, использующих Kotlin coroutines и принимающих приостанавливаемые функциональные типы. Теперь вы можете структурировать свой код, поместив необходимое поведение в отдельный класс, реализующий приостанавливаемый функциональный тип.

class MyClickAction : suspend () -> Unit {
    override suspend fun invoke() { TODO() }
}

fun launchOnClick(action: suspend () -> Unit) {}

Вы можете использовать экземпляр этого класса, где ранее разрешались только лямбды и ссылки на приостанавливаемые функции: launchOnClick(MyClickAction()).

В настоящее время существуют два ограничения, обусловленные особенностями реализации:

  • Вы не можете смешивать обычные функциональные типы и приостанавливаемые в списке супертипов.

  • Вы не можете использовать несколько приостанавливаемых функциональных супертипов.

Стабильные преобразования `suspend`

Kotlin 1.6.0 предоставляет стабильные преобразования из обычных функциональных типов в приостанавливаемые. Начиная с 1.4.0, эта функция поддерживала функциональные литералы и ссылки на вызываемые объекты. С 1.6.0 она работает с любыми выражениями. В качестве аргумента вызова теперь можно передавать любое выражение подходящего обычного функционального типа, где ожидается приостанавливаемый тип. Компилятор автоматически выполнит неявное преобразование.

fun getSuspending(suspending: suspend () -> Unit) {}

fun suspending() {}

fun test(regular: () -> Unit) {
    getSuspending { }           // OK
    getSuspending(::suspending) // OK
    getSuspending(regular)      // OK
}

Стабильное создание экземпляров аннотационных классов

Kotlin 1.5.30 ввел экспериментальную поддержку создания экземпляров аннотационных классов на платформе JVM. В 1.6.0 эта функция доступна по умолчанию как для Kotlin/JVM, так и для Kotlin/JS.

Подробнее об инстанцировании аннотационных классов в этом KEEP.

Улучшенный вывод типов для рекурсивных обобщенных типов

В Kotlin 1.5.30 было внесено улучшение в вывод типов для рекурсивных обобщенных типов, позволившее выводить аргументы их типов, основываясь только на верхних границах соответствующих параметров типа. Улучшение было доступно с опцией компилятора. В версии 1.6.0 и выше оно включено по умолчанию.

// Before 1.5.30
val containerA = PostgreSQLContainer<Nothing>(DockerImageName.parse("postgres:13-alpine")).apply {
  withDatabaseName("db")
  withUsername("user")
  withPassword("password")
  withInitScript("sql/schema.sql")
}

// With compiler option in 1.5.30 or by default starting with 1.6.0
val containerB = PostgreSQLContainer(DockerImageName.parse("postgres:13-alpine"))
  .withDatabaseName("db")
  .withUsername("user")
  .withPassword("password")
  .withInitScript("sql/schema.sql")

Изменения в выводе типов для билдеров

Вывод типов для билдеров — это вид вывода типов, полезный при вызове универсальных функций-билдеров. Он может выводить аргументы типа вызова с помощью информации о типах из вызовов внутри лямбда-аргумента.

Мы вносим несколько изменений, приближающих нас к полной стабильности вывода типов для билдеров. Начиная с 1.6.0:

  • Вы можете делать вызовы, возвращающие экземпляр типа, который еще не выведен, внутри лямбды билдера, без указания опции компилятора -Xunrestricted-builder-inference, представленной в 1.5.30.

  • С помощью -Xenable-builder-inference вы можете создавать свои собственные билдеры без применения аннотации @BuilderInference.

    Обратите внимание, что клиентам этих билдеров потребуется указать ту же опцию компилятора -Xenable-builder-inference.

  • С помощью -Xenable-builder-inference вывод типов для билдеров автоматически активируется, если стандартный вывод типов не может получить достаточную информацию о типе.

Узнайте, как создавать пользовательские универсальные билдеры.

Поддержка аннотаций на параметрах типов классов

Поддержка аннотаций на параметрах типов классов выглядит следующим образом:

@Target(AnnotationTarget.TYPE_PARAMETER)
annotation class BoxContent

class Box<@BoxContent T> {}

Аннотации на всех параметрах типа передаются в байт-код JVM, поэтому обработчики аннотаций могут их использовать.

Для понимания мотивационной ситуации ознакомьтесь с этим тикетом YouTrack.

Узнайте больше об аннотациях.

Поддержка предыдущих версий API в течение более длительного периода

Начиная с Kotlin 1.6.0, мы будем поддерживать разработку для трёх предыдущих версий API вместо двух, наряду с текущей стабильной версией. В настоящее время мы поддерживаем версии 1.3, 1.4, 1.5 и 1.6.

Kotlin/JVM

Для Kotlin/JVM, начиная с версии 1.6.0, компилятор может генерировать классы с байткодом, соответствующим JVM 17. Новая версия языка также включает оптимизированные делегированные свойства и повторяющиеся аннотации, которые были запланированы:

  • Повторяющиеся аннотации с сохранением во время выполнения для целевой JVM 1.8

  • Оптимизация делегированных свойств, вызывающих get/set для данного экземпляра KProperty

Повторяющиеся аннотации с сохранением во время выполнения для целевой JVM 1.8

Java 8 представила повторяющиеся аннотации, которые могут применяться несколько раз к одному элементу кода. Для этого требуется два объявления в коде Java: сама повторяющаяся аннотация, помеченная @java.lang.annotation.Repeatable, и содержащая аннотация для хранения её значений.

В Kotlin повторяющиеся аннотации требуют только @kotlin.annotation.Repeatable для объявления аннотации, чтобы сделать её повторяющейся. До версии 1.6.0 эта функция поддерживала только SOURCE сохранение и была несовместима с повторяющимися аннотациями Java. В Kotlin 1.6.0 эти ограничения устранены. @kotlin.annotation.Repeatable теперь принимает любое сохранение и делает аннотацию повторяющейся как в Kotlin, так и в Java. Повторяющиеся аннотации Java теперь также поддерживаются со стороны Kotlin.

Хотя вы можете объявить содержащую аннотацию, это необязательно. Например:

  • Если аннотация @Tag помечена @kotlin.annotation.Repeatable, компилятор Kotlin автоматически сгенерирует класс содержащей аннотации под именем @Tag.Container:

    @Repeatable 
    annotation class Tag(val name: String)
    
    // The compiler generates @Tag.Container containing annotation
    
  • Чтобы задать пользовательское имя для содержащей аннотации, примените @kotlin.jvm.JvmRepeatable мета-аннотацию и передайте явно объявленный класс содержащей аннотации в качестве аргумента:

    @JvmRepeatable(Tags::class)
    annotation class Tag(val name: String)
    
    annotation class Tags(val value: Array<Tag>)
    

Рефлексия Kotlin теперь поддерживает как повторяющиеся аннотации Kotlin, так и Java с помощью новой функции KAnnotatedElement.findAnnotations().

Дополнительную информацию о повторяющихся аннотациях Kotlin можно найти в этом KEEP.

Оптимизация делегированных свойств, вызывающих get/set для данного экземпляра KProperty

Мы оптимизировали сгенерированный байт-код JVM, исключив поле $delegate и сгенерировав прямой доступ к указанному свойству.

Например, в следующем коде

class Box<T> {
    private var impl: T = ...

    var content: T by ::impl
}

Kotlin больше не генерирует поле content$delegate. Методы доступа к свойству переменной content вызывают переменную impl напрямую, минуя операторы getValue/setValue делегированного свойства и тем самым исключая необходимость в объекте ссылки на свойство типа KProperty.

Спасибо нашим коллегам из Google за реализацию!

Узнайте больше о делегированных свойствах.

Kotlin/Native

Kotlin/Native получает множество улучшений и обновлений компонентов, некоторые из них находятся в стадии предварительного просмотра:

  • Предварительный просмотр нового менеджера памяти

  • Поддержка Xcode 13

  • Компиляция целевых платформ Windows на любом хосте

  • Обновления LLVM и линковщика

  • Улучшения производительности

  • Единый ABI компилятора-плагина с JVM и JS IR бэкендами

  • Подробные сообщения об ошибках для сбоев склейки klib

  • Переработанный API обработки необработанных исключений

Предварительный просмотр нового менеджера памяти

Новый менеджер памяти Kotlin/Native находится в экспериментальной стадии. Он может быть удалён или изменён в любое время. Требуется опциональное включение (см. подробности ниже), и его следует использовать только для оценочных целей. Мы будем рады получить ваши отзывы по этому вопросу в YouTrack.

С Kotlin 1.6.0 вы можете опробовать предварительный просмотр нового менеджера памяти Kotlin/Native. Он приближает нас к устранению различий между платформами JVM и Native, чтобы обеспечить согласованный опыт разработчика в многоплатформенных проектах.

Одно из заметных изменений — это ленивая инициализация свойств верхнего уровня, как в Kotlin/JVM. Свойство верхнего уровня инициализируется при первом доступе к свойству или функции верхнего уровня из того же файла. Этот режим также включает глобальную межпроцедурную оптимизацию (включена только для релизных библиотек), которая удаляет излишние проверки инициализации.

Недавно мы опубликовали статью в блоге о новом менеджере памяти. Прочитайте её, чтобы узнать о текущем состоянии нового менеджера памяти и найти примерные проекты, или переходите прямо к инструкциям по миграции, чтобы попробовать его самостоятельно. Пожалуйста, проверьте, как новый менеджер памяти работает в ваших проектах, и поделитесь отзывами в нашем системе отслеживания ошибок, YouTrack.

Поддержка Xcode 13

Kotlin/Native 1.6.0 поддерживает Xcode 13 — последнюю версию Xcode. Вы можете смело обновлять Xcode и продолжать работать над своими Kotlin-проектами для операционных систем Apple.

Новые библиотеки, добавленные в Xcode 13, недоступны для использования в Kotlin 1.6.0, но мы добавим поддержку для них в будущих версиях.

Компиляция целевых платформ Windows на любом хосте

Начиная с версии 1.6.0, вам не нужен хост Windows для компиляции целевых платформ Windows mingwX64 и mingwX86. Их можно компилировать на любом хосте, поддерживающем Kotlin/Native.

Обновления LLVM и линковщика

Мы переработали зависимость LLVM, которую Kotlin/Native использует внутри. Это приносит различные преимущества, в том числе:

  • Обновленная версия LLVM до 11.1.0.

  • Уменьшен размер зависимости. Например, на macOS он теперь составляет около 300 МБ вместо 1200 МБ в предыдущей версии.

  • Исключена зависимость от библиотеки ncurses5, которая недоступна в современных дистрибутивах Linux.

В дополнение к обновлению LLVM, Kotlin/Native теперь использует линковщик LLD (линковщик из проекта LLVM) для целей MingGW. Он предоставляет различные преимущества по сравнению с ранее используемым линковщиком ld.bfd и позволит нам улучшить производительность исполняемых файлов во время выполнения и поддерживать кэш компилятора для целей MinGW. Обратите внимание, что LLD требует импортных библиотек для связи с DLL. Узнайте больше в этом потоке Stack Overflow.

Улучшения производительности

Kotlin/Native 1.6.0 предоставляет следующие улучшения производительности:

  • Время компиляции: кэши компилятора включены по умолчанию для linuxX64 и iosArm64 целей. Это ускоряет большинство компиляций в отладочном режиме (кроме первой). Измерения показали увеличение скорости примерно на 200% для наших тестовых проектов. Кэши компилятора были доступны для этих целей с Kotlin 1.5.0 с дополнительными свойствами Gradle; теперь вы можете их удалить.

  • Время выполнения: итерация по массивам с помощью циклов for теперь до 12% быстрее благодаря оптимизациям в сгенерированном коде LLVM.

Единый ABI компилятора-плагина с JVM и JS IR бэкендами

Вариант использования общего ABI компилятора-плагина для Kotlin/Native находится в экспериментальной стадии. Он может быть удалён или изменён в любое время. Требуется опциональное включение (см. подробности ниже), и его следует использовать только для оценочных целей. Мы будем рады получить ваши отзывы по этому вопросу в YouTrack.

В предыдущих версиях авторы плагинов компилятора должны были предоставлять отдельные артефакты для Kotlin/Native из-за различий в ABI.

Начиная с версии 1.6.0, плагин Kotlin Multiplatform Gradle способен использовать встраиваемый JAR-файл компилятора (используемый для JVM и JS IR бэкендов) для Kotlin/Native. Это шаг к унификации опыта разработки плагинов компилятора, так как теперь вы можете использовать те же артефакты плагинов компилятора для Native и других поддерживаемых платформ.

Это предварительная версия такой поддержки и требует опционального включения. Чтобы начать использовать общие артефакты плагинов компилятора для Kotlin/Native, добавьте следующую строку в gradle.properties: kotlin.native.useEmbeddableCompilerJar=true.

В будущем мы планируем использовать встраиваемый JAR-файл компилятора для Kotlin/Native по умолчанию, поэтому для нас очень важно узнать, как работает предварительный просмотр для вас.

Если вы автор плагина компилятора, пожалуйста, попробуйте этот режим и проверьте, работает ли он для вашего плагина. Обратите внимание, что в зависимости от структуры вашего плагина могут потребоваться шаги по миграции. См. данную проблему в YouTrack для инструкций по миграции и оставьте свои отзывы в комментариях.

Подробные сообщения об ошибках для сбоев склейки klib

Компилятор Kotlin/Native теперь предоставляет подробные сообщения об ошибках для ошибок склейки klib. Теперь сообщения содержат четкие описания ошибок, а также информацию о возможных причинах и способах их исправления.

Например:

  • 1.5.30:

    e: java.lang.IllegalStateException: IrTypeAliasSymbol expected: Unbound public symbol for public kotlinx.coroutines/CancellationException|null[0]
    <stack trace>
    
  • 1.6.0:

    e: The symbol of unexpected type encountered during IR deserialization: IrClassPublicSymbolImpl, kotlinx.coroutines/CancellationException|null[0].
    IrTypeAliasSymbol is expected.
    
    This could happen if there are two libraries, where one library was compiled against the different version of the other library than the one currently used in the project.
    Please check that the project configuration is correct and has consistent versions of dependencies.
    
    The list of libraries that depend on "org.jetbrains.kotlinx:kotlinx-coroutines-core (org.jetbrains.kotlinx:kotlinx-coroutines-core-macosx64)" and may lead to conflicts:
    <list of libraries and potential version mismatches>
    
    Project dependencies:
    <dependencies tree>
    

Переработанный API обработки необработанных исключений

Мы объединили обработку необработанных исключений во всем времени выполнения Kotlin/Native и представили стандартную обработку как функцию processUnhandledException(throwable: Throwable) для использования в пользовательских средах выполнения, таких как kotlinx.coroutines. Эта обработка также применяется к исключениям, которые выходят за пределы операции в Worker.executeAfter(), но только для нового менеджера памяти.

Улучшения API также повлияли на обработчики, установленные setUnhandledExceptionHook(). Ранее такие обработчики сбрасывались после того, как время выполнения Kotlin/Native вызывало обработчик с необработанным исключением, и программа всегда завершалась сразу после этого. Теперь эти обработчики могут использоваться более одного раза, и если вы хотите, чтобы программа всегда завершалась при возникновении необработанного исключения, либо не устанавливайте обработчик необработанных исключений (setUnhandledExceptionHook()), либо убедитесь, что вызывается terminateWithUnhandledException() в конце вашего обработчика. Это поможет вам отправлять исключения в стороннюю службу отслеживания сбоев (например, Firebase Crashlytics), а затем завершить программу. Исключение, которое выходит за пределы main(), и исключения, пересекающие границу взаимодействия, всегда будут завершать программу, даже если обработчик не вызвал terminateWithUnhandledException().

Kotlin/JS

Мы продолжаем работу над стабилизацией бэкенда IR для компилятора Kotlin/JS. Теперь в Kotlin/JS есть возможность отключить загрузку Node.js и Yarn.

Возможность использования установленных Node.js и Yarn

Теперь вы можете отключить загрузку Node.js и Yarn при сборке проектов Kotlin/JS и использовать уже установленные на хосте экземпляры. Это полезно для сборки на серверах без подключения к интернету, таких как сервера CI.

Чтобы отключить загрузку внешних компонентов, добавьте следующие строки в ваш build.gradle(.kts):

  • Yarn:

    rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin> {
        rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().download = false // or true for default behavior
    }
    
    rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin) {
        rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension).download = false
    }
    
  • Node.js:

    rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {
        rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().download = false // or true for default behavior
    }
    
    
    rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin) {
        rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension).download = false
    }
    

Kotlin Gradle плагин

В Kotlin 1.6.0, мы изменили уровень устаревания класса KotlinGradleSubplugin на 'ERROR'. Этот класс использовался для написания плагинов компилятора. В последующих релизах мы удалим этот класс. Используйте класс KotlinCompilerPluginSupportPlugin вместо него.

Мы удалили опцию сборки kotlin.useFallbackCompilerSearch и опции компилятора noReflect и includeRuntime. Опция компилятора useIR была скрыта и будет удалена в будущих релизах.

Узнайте больше о поддерживаемых опциях компилятора в Kotlin Gradle плагине.

END_OF_DOCUMENT_MARKER

Стандартная библиотека

Новая версия стандартной библиотеки 1.6.0 стабилизирует экспериментальные возможности, вводит новые и унифицирует своё поведение на разных платформах:

  • Новые функции readline

  • Стабильный typeOf()

  • Стабильные билдеры коллекций

  • Стабильный API Duration

  • Разделение регулярных выражений на последовательность

  • Операции циклического сдвига битов для целых чисел

  • Изменения для replace() и replaceFirst() в JS

  • Улучшения существующего API

  • Устаревания

Новые функции readline

Kotlin 1.6.0 предлагает новые функции для обработки стандартного ввода: readln() и readlnOrNull().

Пока новые функции доступны только для платформ JVM и Native.

Предыдущие версии

Альтернатива 1.6.0

Использование

readLine()!!

readln()

Читает строку из stdin и возвращает ее, или выбрасывает RuntimeException, если достигнут конец файла.

readLine()

readlnOrNull()

Читает строку из stdin и возвращает ее, или возвращает null, если достигнут конец файла.

Мы считаем, что устранение необходимости использования !! при чтении строки улучшит опыт для новичков и упростит обучение Kotlin. Чтобы сделать имя операции чтения строки согласованным с его println() аналогом, мы решили сократить имена новых функций до 'ln'.

println("What is your nickname?")
val nickname = readln()
println("Hello, $nickname!")
fun main() {
//sampleStart
    var sum = 0
    while (true) {
        val nextLine = readlnOrNull().takeUnless { 
            it.isNullOrEmpty() 
        } ?: break
        sum += nextLine.toInt()
    }
    println(sum)
//sampleEnd
}

Существующая readLine() функция будет иметь более низкий приоритет, чем readln() и readlnOrNull() в завершении кода вашего IDE. Инспекции IDE также будут рекомендовать использование новых функций вместо устаревшей readLine().

В будущих выпусках мы планируем постепенно устаревать readLine() функцию.

Стабильный typeOf()

Версия 1.6.0 вводит стабильную функцию typeOf(), закрывая один из главных пунктов дорожной карты.

С 1.3.40, typeOf() была доступна на платформе JVM в качестве экспериментального API. Теперь вы можете использовать её на любой платформе Kotlin и получить KType представление любого типа Kotlin, который может определить компилятор:

inline fun <reified T> renderType(): String {
    val type = typeOf<T>()
    return type.toString()
}

fun main() {
    val fromExplicitType = typeOf<Int>()
    val fromReifiedType = renderType<List<Int>>()
}

Стабильные билдеры коллекций

В Kotlin 1.6.0 функции билдеров коллекций были повышены до стабильного статуса. Коллекции, возвращаемые билдерами коллекций, теперь сериализуемы в их состоянии только для чтения.

Теперь вы можете использовать buildMap(), buildList() и buildSet() без аннотации opt-in:

fun main() {
//sampleStart
    val x = listOf('b', 'c')
    val y = buildList {
        add('a')
        addAll(x)
        add('d')
    }
    println(y)  // [a, b, c, d]
//sampleEnd
}

Стабильный API Duration

Класс Duration для представления продолжительности во времени в различных единицах измерения имеет статус стабильный. В 1.6.0 API Duration претерпел следующие изменения:

  • Первый компонент функции toComponents(), которая разлагает продолжительность на дни, часы, минуты, секунды и наносекунды, теперь имеет тип Long вместо Int. Раньше, если значение не помещалось в диапазон Int, оно приводилось к этому диапазону. С типом Long вы можете разложить любое значение в диапазоне продолжительности без обрезания значений, не помещающихся в Int.

  • Перечисление DurationUnit теперь является самостоятельным, а не псевдонимом java.util.concurrent.TimeUnit на JVM. Мы не нашли убедительных случаев, в которых использование typealias DurationUnit = TimeUnit было бы полезным. Кроме того, экспонирование TimeUnit API через псевдоним может ввести в заблуждение пользователей DurationUnit.

  • В ответ на отзывы сообщества, мы возвращаем расширяющие свойства, такие как Int.seconds. Но мы хотели бы ограничить их применение, поэтому поместили их в компаньон класса Duration. Хотя IDE по-прежнему может предлагать расширения в завершении и автоматически вставлять импорт из компаньона, в будущем мы планируем ограничить это поведение случаями, когда ожидается тип Duration.

    import kotlin.time.Duration.Companion.seconds
    
    fun main() {
    //sampleStart
        val duration = 10000
        println("There are ${duration.seconds.inWholeMinutes} minutes in $duration seconds")
        // There are 166 minutes in 10000 seconds
    //sampleEnd
    }
    

    Мы рекомендуем заменить ранее введённые компаньон-функции, такие как Duration.seconds(Int), и устаревшие глобальные расширения, такие как Int.seconds, новыми расширениями в Duration.Companion.

    Такая замена может вызвать неоднозначность между старыми глобальными расширениями и новыми расширениями компаньона. Убедитесь, что используете импорт с подстановкой "*package kotlin.time* – import kotlin.time.* – перед выполнением автоматической миграции.

Разделение регулярных выражений на последовательность

Функции Regex.splitToSequence(CharSequence) и CharSequence.splitToSequence(Regex) повышены до стабильного статуса. Они разбивают строку по совпадениям с заданным регулярным выражением, но возвращают результат в виде последовательности, так что все операции с этим результатом выполняются лениво:

fun main() {
//sampleStart
    val colorsText = "green, red, brown&blue, orange, pink&green"
    val regex = "[,\\s]+".toRegex()
    val mixedColor = regex.splitToSequence(colorsText)
    // or
    // val mixedColor = colorsText.splitToSequence(regex)
        .onEach { println(it) }
        .firstOrNull { it.contains('&') }
    println(mixedColor) // "brown&blue"
//sampleEnd
}

Операции циклического сдвига битов для целых чисел

В Kotlin 1.6.0 функции rotateLeft() и rotateRight() для битовых операций стали стабильными. Функции вращают двоичное представление числа влево или вправо на заданное количество битов:

fun main() {
//sampleStart
    val number: Short = 0b10001
    println(number
        .rotateRight(2)
        .toString(radix = 2)) // 100000000000100
    println(number
        .rotateLeft(2)
        .toString(radix = 2))  // 1000100
//sampleEnd
}
END_OF_DOCUMENT_MARKER

Изменения для replace() и replaceFirst() в JS

До Kotlin 1.6.0, функции replace() и replaceFirst() Regex работали по-разному в Java и JS, когда строка замены содержала ссылку на группу. Для обеспечения согласованного поведения на всех целевых платформах, мы изменили их реализацию в JS.

Вхождения ${name} или $index в строке замены заменяются подпоследовательностями, соответствующими захваченным группам с указанным индексом или именем:

  • $index – первая цифра после '$' всегда обрабатывается как часть ссылки на группу. Последующие цифры включаются в index только в том случае, если они образуют корректную ссылку на группу. Только цифры '0'–'9' рассматриваются как потенциальные компоненты ссылки на группу. Обратите внимание, что индексы захваченных групп начинаются с '1'. Группа с индексом '0' соответствует всему совпадению.

  • ${name} – имя группы может состоять из латинских букв 'a'–'z', 'A'–'Z' или цифр '0'–'9'. Первый символ должен быть буквой.

    Имена групп в шаблонах замены в настоящее время поддерживаются только в JVM.

  • Чтобы включить следующий символ в строку замены как литерал, используйте обратную косую черту \:

    fun main() {
    //sampleStart
        println(Regex("(.+)").replace("Kotlin", """\$ $1""")) // $ Kotlin
        println(Regex("(.+)").replaceFirst("1.6.0", """\\ $1""")) // \ 1.6.0
    //sampleEnd
    }
    

    Вы можете использовать Regex.escapeReplacement(), если строка замены должна обрабатываться как строка-литерал.

Улучшения существующего API

  • В версии 1.6.0 была добавлена инфиксная расширяющая функция для Comparable.compareTo(). Теперь вы можете использовать инфиксную форму для сравнения двух объектов по порядку:

     class WrappedText(val text: String) : Comparable<WrappedText> {
         override fun compareTo(other: WrappedText): Int =
             this.text compareTo other.text
    }
    
  • Regex.replace() в JS теперь также не является инлайновой для унификации её реализации на всех платформах.

  • Функции compareTo() и equals() для строк, а также функция isBlank() для объектов типа CharSequence теперь работают в JS точно так же, как и в JVM. Раньше были расхождения при работе с символами, не являющимися ASCII.

Устаревшие функции

В Kotlin 1.6.0 мы начинаем цикл устаревания, добавив предупреждение для некоторых API stdlib, специфичных для JS.

Функции concat(), match() и matches() для строк

  • Для конкатенации строки со строковым представлением другого объекта используйте plus() вместо concat().

  • Для поиска всех вхождений регулярного выражения в входных данных используйте функцию findAll() класса Regex вместо String.match(regex: String).

  • Для проверки, соответствует ли регулярное выражение всему входному значению, используйте функцию matches() класса Regex вместо String.matches(regex: String).

Функция sort() для массивов, принимающая функции сравнения

Мы устарели функцию Array<out T>.sort() и инлайновые функции ByteArray.sort(), ShortArray.sort(), IntArray.sort(), LongArray.sort(), FloatArray.sort(), DoubleArray.sort(), и CharArray.sort(), которые сортировали массивы в соответствии с порядком, заданным функцией сравнения. Используйте другие стандартные функции библиотеки для сортировки массивов.

См. раздел упорядочение коллекций для справки.

Инструменты

Kover – инструмент для измерения охвата кода для Kotlin

Плагин Kover Gradle является экспериментальным. Мы ценим ваши отзывы на GitHub.

С Kotlin 1.6.0 мы представляем Kover – плагин Gradle для IntelliJ и JaCoCo агентов для измерения охвата Kotlin кода. Он работает со всеми конструкциями языка, включая инлайновые функции.

Узнайте больше о Kover на его репозитории GitHub или в этом видео:

Coroutines 1.6.0-RC

kotlinx.coroutines 1.6.0-RC вышел с несколькими функциями и улучшениями:

  • Поддержка нового менеджера памяти Kotlin/Native.

  • Введение API диспетчера вид, которое позволяет ограничить параллелизм без создания дополнительных потоков.

  • Миграция с Java 6 на Java 8 в качестве целевой версии.

  • kotlinx-coroutines-test с новым переработанным API и поддержкой многоплатформенности.

  • Введение CopyableThreadContextElement, которая предоставляет сопрограммам безопасный доступ для записи в переменные ThreadLocal.

Узнайте больше в журнале изменений.

Миграция на Kotlin 1.6.0

IntelliJ IDEA и Android Studio предложат обновить плагин Kotlin до 1.6.0, как только он станет доступен.

Чтобы мигрировать существующие проекты на Kotlin 1.6.0, измените версию Kotlin на 1.6.0 и повторно импортируйте свой проект Gradle или Maven. Узнайте, как обновить Kotlin до 1.6.0.

Чтобы начать новый проект с Kotlin 1.6.0, обновите плагин Kotlin и запустите Мастер проектов из Файл | Новый | Проект.

Новый компилятор командной строки доступен для скачивания на странице выпуска GitHub.

Kotlin 1.6.0 является релизом с новыми функциями и, следовательно, может содержать изменения, несовместимые с вашим кодом, написанным для предыдущих версий языка. Найдите подробный список таких изменений в Руководстве по совместимости для Kotlin 1.6.

Последнее изменение: 07 апреля 2022
Что нового в Kotlin 1.6.20 Что нового в Kotlin 1.5.30

© 2010–2022 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew16.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API