Kotlin 1.8.0の変更点

※ソース記事は[こちら](https://kotlinlang.org/docs/whatsnew18.html#updated-jvm-compilation-target)
※Kotlin/JS、Kotlin/Nativeについては割愛します。
[リリース日：2022/12/28](https://kotlinlang.org/docs/releases.html#release-details)
Kotlin 1.8.0リリースが世に出され、ここにいくつかの最大のハイライトがある。
- JVMのための新しいの実験的機能：ディレクトリ内容の再帰的なコピーと削除
- kotlin-reflect性能の改善
- より良いデバッグ経験のための新しい-Xdebugコンパイラオプション
- `kotlin-stdlib-jdk7`と`kotlin-stdlib-jdk8`の`kotlin-stdlib`へのマージ
- Objective-C/Swiftとの相互運用性の向上
- Gradle 7.3との互換性

# IDEのサポート
1.8.0をサポートするKotlinプラグインはこちらで利用可能である。
|  IDE  |  サポートバージョン  |
| ---- | ---- |
|  IntelliJ IDEA  |  2021.3,2022.1,2022.2  |
|  Android Studio  | Electric Eel (221), Flamingo (222)  |

::: note
IntelliJ IDEA 2022.3では、IDEプラグインの更新なしで、プロジェクトをKotlin 1.8.0の更新することができる。
IntelliJ IDEA 2022.3で既存のプロジェクトをKotlin 1.8.0に移行するには、Kotlin versionを1.8.0に変更して、GradleまたはMavenプロジェクトを再インポートする。
:::
# Kotlin/JVM
Kotlin 1.8.0から、コンパイラはJVM19に対応したバイトコードバージョンでクラスを生成することができる。新しい言語バージョンには以下も含まれる。
- JVMアノテーションターゲットの生成をオフに切り替えるコンパイラ引数
- 最適化を無効にするための新しい`-Xdebug`コンパイラオプション
- 古いバックエンドの削除
- Lombokの<span>@</span>Builderアノテーションのサポート
## TYPE_USEとTYPE_PARAMETERアノテーションターゲットを生成しない機能
KotlinアノテーションがKotlinターゲットの間で`TYPE`を持つ場合、アノテーションはJavaのアノテーションターゲットのリスト内で、`java.lang.annotation.ElementType.TYPE_USE`をマッピングする。これは`TYPE_PARAMETER`Kotlinアノテーションターゲットが`java.lang.annotation.ElementType.TYPE_PARAMETER`ターゲットにマッピングすることに似ている。これはAPIレベル26未満のAndroidクライアントにとって問題である。というのはAPIにこれらのターゲットを持っていないためである。
Kotlin 1.8.0から、`TYPE_USE`と`TYPE_PARAMETER`アノテーションターゲットを生成しないようするためには、新しいコンパイラ引数`-Xno-new-java-annotation-targets`を使うことができる。
## 最適化を無効にする新しいコンパイラオプション
Kotlin 1.8.0では、新しい`-Xdebug`コンパイラオプションが追加され、それにより、より良いデバッグ経験のために最適化が無効になる。今のところ、そのオプションは、コルーチンのための「optimized outされた」機能を無効にする。将来はより多くの最適化を追加した後で、このオプションでそれらも無効にするだろう。
「optimized out」機能は、suspend関数を使うときに、変数を最適化する。しかし変数の値が見れないために、最適化された変数のあるコードをデバッグすることは難しい。

::: note alert
このフラグを本番では使ってはいけない。`-Xdebug`経由でこの機能を無効にすると、[メモリリーク](https://youtrack.jetbrains.com/issue/KT-48678/Coroutine-debugger-disable-was-optimised-out-compiler-feature#focus=Comments-27-6015585.0-0)が起こりうる。
:::

## 古いバックエンドの削除
Kotlin 1.5.0で、IRベースのバックエンドが[Stable](https://kotlinlang.org/docs/components-stability.html)になったと[アナウンスされた](https://kotlinlang.org/docs/whatsnew15.html#stable-jvm-ir-backend)。これはKotiln 1.4.*からの古いバックエンドは非推奨になったという意味である。Kotlin 1.8.0で完全に古いバックエンドが削除された。延長線上で、`-Xuse-old-backend`コンパイラオプションとGradleの`useOldBackend`オプションが削除された。
## Lombokの<span>@</span>Builderアノテーションのサポート
コミュニティにより、[Kotlin Lombok:生成されたビルダー(<span>@</span>Builder)のサポート](https://youtrack.jetbrains.com/issue/KT-46959)のYouTrack課題に多くの投票がされたため、[<span>@</span>Builderアノテーション](https://projectlombok.org/features/Builder)をサポートせざるを得なかった。
`@SuperBuilder`と`@Tolerate`アノテーションをサポートする計画はまだないが、もし十分に多くの人々が[@SuperBuilder](https://youtrack.jetbrains.com/issue/KT-53563/Kotlin-Lombok-Support-SuperBuilder)と[@Tolerate](https://youtrack.jetbrains.com/issue/KT-53564/Kotlin-Lombok-Support-Tolerate)の課題のために、投票すれば再考するだろう。
[Lombokコンパイラプラグインの設定方法を学ぶ](https://kotlinlang.org/docs/lombok.html#gradle)
# Gradle
Kotlin 1.8.0はGradle 7.2と7.3に完全に対応している。Gradleバージョンを最新のリリースにアップデートすることも可能だが、もしそうすると、非推奨警告やいくつかの新しいGradleの機能が動作しないかもしれないということに注意してほしい。
このバージョンでは多くの変更がもたらされている。
## Gradle lazyプロパティとしてKotllinコンパイラオプションの公開
[Gradle lazyプロパティ](https://docs.gradle.org/current/userguide/lazy_configuration.html)としてKotlinコンパイラオプションを公開し、Kotlinタスクによりよく統合するため、多くの変更が行われた。
- compileタスクは新しい`compilerOptions`入力を持ち、それは既存の`kotlinOptions`と同じだが、Gradle Properties APIからの[Property](https://docs.gradle.org/current/javadoc/org/gradle/api/provider/Property.html)を戻り型として使う。
```gradle
tasks.named("compileKotlin", org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile::class.java) {
    compilerOptions {
        useK2.set(true)
    }
}
```
- Kotlinツールタスクの`KotlinJsDce`と`KotlinNativeLink`は新しい`toolOptions`入力を持ち、それは既存の`kotlinOptions`入力と似ている。
- 新しい入力は[@Nested Gradleアノテーション](https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/Nested.html)を持つ。入力内部のそれぞれのプロパティは、`@Input`や`@Internal`のような関連するGradleアノテーションを持つ。
- Kotlin GradleプラグインAPIの生成物は、二つの新しいインターフェイスを持つ。
   - `org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask` これは`compilerOptions`入力と`compileOptions()`メソッドを持つ。すべてのKotlinコンパイルタスクはこのインターフェイスを実装する。
   - `org.jetbrains.kotlin.gradle.tasks.KotlinToolTask` これは`toolOptions`入力と`toolOptions()`メソッドを持つ。すべてのKotlinツールタスク(`KotlinJsDce`、`KotlinNativeLink`、`KotlinNativeLinkArtifactTask`)はこのインターフェイスを実装する。
- いくつかの`compilerOptions`は`String`型の代わりに新しい型を使う。
   - [JvmTarget](https://github.com/JetBrains/kotlin/blob/1.8.0/libraries/tools/kotlin-gradle-compiler-types/src/generated/kotlin/org/jetbrains/kotlin/gradle/dsl/JvmTarget.kt)
   - [KotlinVersion](https://github.com/JetBrains/kotlin/blob/1.8.0/libraries/tools/kotlin-gradle-compiler-types/src/generated/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinVersion.kt)(`apiVersion`と`languageVersion`入力のため)
   - [JsMainFunctionExecutionMode](https://github.com/JetBrains/kotlin/blob/1.8.0/libraries/tools/kotlin-gradle-compiler-types/src/generated/kotlin/org/jetbrains/kotlin/gradle/dsl/JsMainFunctionExecutionMode.kt)
   - [JsModuleKind](https://github.com/JetBrains/kotlin/blob/1.8.0/libraries/tools/kotlin-gradle-compiler-types/src/generated/kotlin/org/jetbrains/kotlin/gradle/dsl/JsModuleKind.kt)
   - [JsSourceMapEmbedMode](https://github.com/JetBrains/kotlin/blob/1.8.0/libraries/tools/kotlin-gradle-compiler-types/src/generated/kotlin/org/jetbrains/kotlin/gradle/dsl/JsSourceMapEmbedMode.kt)
   例えば、`kotlinOptions.jvmTarget = "11"`の代わりに、`compilerOptions.jvmTarget.set(JvmTarget.JVM_11)`を使うことができる。
   `kotlinOptions`の型の変更は無く、それらは内部的に`compilerOptions`型に変換されている。
- Kotlin GradleプラグインAPIは、以前のリリースとバイナリレベルで互換性がある。しかしいくつかのソースと、ABI(Application Binary Interface)を破る変更が`kotlin-gradle-plugin`成果物に存在する。これらの変更のほとんどは、いくつかの内部型に対する追加のジェネリックパラメータに関係している。一つの重要な変更は、`KotlinNativeLink`タスクはもはや`AbstractKotlinNativeCompile`タスクを継承していないということである。
- `KotlinJsCompilerOptions.outputFile`と関連する`KotlinJsOptions.outputFile`オプションは非推奨である。代わりに`Kotlin2JsCompile.outputFileProperty`タスクを使ってほしい。

:::note
Kotlin Gradleプラグインは、Android拡張に対して`KotlinJvmOptions`DSLがまだ追加されている。
```
android {
    kotlinOptions {
        jvmTarget = "11"
    }
}
```
これは`compilerOptions`DSLがモジュールレベルで追加されるときに、[この問題](https://youtrack.jetbrains.com/issue/KT-15370/Gradle-DSL-add-module-level-kotlin-options)の範囲内において変更されるだろう。
:::
### 制限

::: note warn
`kotilnOptions`タスク入力と、`kotlinOptions{....}`タスクDSLは、サポートモードであり、今後のリリースで非推奨になるだろう。改善は`compilerOptions`と`toolOptions`に対してのみ、なされるだろう。
:::
`kotlinOptions`に対するどのようなセッター、ゲッター呼び出しも、`compilerOptions`内の関連するプロパティに移譲されている。これは次の制限をもたらしている。
- `compilerOptions`と`kotlinOptions`は、タスクの実行フェーズでは変更できない。(上の段落での一つの例外を参照)
- `freeCompilerArgs`は変更不可能な`List<String>`を返却し、それは例えば`kotlinOptions.freeCompilerArgs.remove("something")`が失敗することを意味する。
- `kotlin-DSL`と[Jetpack Compose](https://developer.android.com/jetpack/compose)を有効にしたAndroid Gradleプラグイン(AGP)を含むいくつかのプラグインは、タスク実行フェーズで`freeCompilerArgs`属性を修正しようとしている。Kotlin 1.8.0ではそのための回避策が追加されている。この回避策により、タスク実行フェーズで`freeCompilerArgs`属性を修正する、どのようなスクリプトもプラグインも許可されるが、ビルドログに警告が生成される。この警告を無効にするには`kotlin.options.suppressFreeCompilerArgsModificationWarning=true`Gradleプロパティを使うこと。Gradleは[kotlin-dslプラグイン](https://github.com/gradle/gradle/issues/22091)と[Jetpack Composeを有効にしたAGP](https://issuetracker.google.com/u/1/issues/247544167)のために修正を追加する予定である。

## 最小サポートバージョンのバージョンアップ
Kotlin 1.8.0から、最小のサポートGradleバージョンが6.8.3であり、最小のサポートAndroid Gradleプラグインバージョンは4.1.3である。
## Kotlinデーモンの代替戦略を無効にする機能
新しい`kotlin.daemon.useFallbackStrategy`Gradleプロパティがあり、デフォルト値は`true`である。値を`false`すると、デーモンの起動や通信の問題でビルドが失敗する。Kotlinコンパイルタスクにも新しい`useDaemonFallbackStrategy`プロパティがあり、両方使うときはこちらがGradleプロパティより優先する。コンパイルを実行するのに十分なメモリが無い場合、ログにそのことについてのメッセージを見ることができる。
Kotlinコンパイラの代替戦略は、デーモンがなぜかで失敗する場合、コンパイルをKotlinデーモンの外部で実行することである。Gradleデーモンが無効の場合、コンパイラは「プロセス外」の戦略を使う。これらの[実行戦略についての文書](https://kotlinlang.org/docs/gradle-compilation-and-caches.html#defining-kotlin-compiler-execution-strategy)でより詳細を確認すること。注意すべきは、別の戦略への無言の代替は、多くのシステムリソースを消費するか、非決定的なビルドにつながるということである。より詳細については、[YouTrack問題](https://youtrack.jetbrains.com/issue/KT-48843/Add-ability-to-disable-Kotlin-daemon-fallback-strategy)を参照のこと。
## 推移的な依存性における最新のkotlin-stdlibバージョンの使用
dependencies内で、例えば`implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.0")`のように明示的にKotlinバージョン1.8.0以上を書く場合、Kotlin Gradleプラグインは、推移的な`kotlin-stdlib-jdk7`と`kotlin-stdlib-jdk8`の依存性のためのKotlinバージョンを使う。これは、異なるstdlibバージョンからクラスの重複を避けるためになされる。([`kotlin-stdlib-jdk7`と`kotlin-stdlib-jdk8`の`kotlin-stdlib`へのマージ](https://kotlinlang.org/docs/whatsnew18.html#updated-jvm-compilation-target)についてより詳細を確認のこと)`kotlin.stdlib.jdk.variants.version.alignment` Gradleプロパティを使って、このふるまいを無効にすることができる。
```
kotlin.stdlib.jdk.variants.version.alignment=false
```
バージョンを揃えるのに問題が発生したときは、ビルドスクリプト内で、`kotlin-bom`に関するプラットフォーム依存性を宣言することで、Kotlin [BOM](https://docs.gradle.org/current/userguide/platforms.html#sub:bom_import)経由ですべてのバージョンを揃えること。
```
implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))
```

その他のケースと推奨の解決法については、[ドキュメント](https://kotlinlang.org/docs/gradle-configure-project.html#other-ways-to-align-versions)内で確認すること。
## 関連するKotlinとJavaのコンパイルタスクに関連するJVMターゲットの必須チェック
::: note 
このセクションは、たとえソースファイルがKotlinのみであり、Javaを使わない場合でも、JVMプロジェクトには当てはまる。
:::
[このリリースから](https://youtrack.jetbrains.com/issue/KT-54993/Raise-kotlin.jvm.target.validation.mode-check-default-level-to-error-when-build-is-running-on-Gradle-8)、Gradle 8.0+(このGradleバージョンはまだリリースされていない)におけるプロジェクトのための、[`kotlin.jvm.target.validation.mode`プロパティ](https://kotlinlang.org/docs/gradle-configure-project.html#check-for-jvm-target-compatibility-of-related-compile-tasks)のデフォルト値は、`error`であり、プラグインはJVMターゲットの非互換性のイベントで、ビルドが失敗するだろう。
`warning`から`error`にデフォルト値を移行するのは、Gradle 8.0へのスムースな移行のための準備ステップである。このプロパティをerrorにし、[ツールチェーンを設定](https://kotlinlang.org/docs/gradle-configure-project.html#gradle-java-toolchains-support)するか、JVMバージョンを手動で揃えることを推奨している。
より詳細には、[ターゲットの互換性チェックをしないとどんな問題が起こるか](https://kotlinlang.org/docs/gradle-configure-project.html#what-can-go-wrong-if-not-checking-targets-compatibility)を確認のこと。
## Kotlin Gradleプラグインの推移的依存性の解決
Kotlin 1.7.0で、[Gradleプラグインバリアントのサポート](https://kotlinlang.org/docs/whatsnew17.html#support-for-gradle-plugin-variants)が導入された。このプラグインバリアントにより、ビルドクラスパスはいくつかの依存性、大抵は`kotlin-gradle-plugin-api`の異なるバージョンに依存する、[`Kotlin Gradleプラグイン`](https://plugins.gradle.org/u/kotlin)の異なるバージョンを持つことができる。これは解決問題につながるため、`kotlin-dsl`プラグインを例として使い、次のような回避方法を提案したい。
Gradle 7.6の`kotlin-dsl`プラグインは、`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`](https://docs.gradle.org/current/javadoc/org/gradle/api/attributes/plugin/GradlePluginApiVersion.html)の値のミスマッチのために、依存性の解決エラーを引き起こすかもしれない。回避策として、バージョンを揃えるためにこの[constraint](https://docs.gradle.org/current/userguide/dependency_constraints.html#sec:adding-constraints-transitive-deps)を追加する。この回避策は、計画にある[Kotlin Gradle Plugin libraries alignment platform](https://youtrack.jetbrains.com/issue/KT-54691/Kotlin-Gradle-Plugin-libraries-alignment-platform)が実装されるまで、必要かもしれない。
```gradle
dependencies {
    constraints {
        implementation("org.jetbrains.kotlin:kotlin-sam-with-receiver:1.8.0")
    }
}
```
このconstraintは、`org.jetbrains.kotlin:kotlin-sam-with-receiver:1.8.0`バージョンを推移的な依存性のためのビルドクラスパスとして使うように強制する。[Gradle issue tracker](https://github.com/gradle/gradle/issues/22510#issuecomment-1292259298)で一つの似たケースについてより詳細を確認できる。
## 非推奨と削除
Kotlin 1.8.0では、次のプロパティとメソッドのための非推奨ライフサイクルが継続している。
- [Kotlin 1.7.0のnotesにおいて](https://kotlinlang.org/docs/whatsnew17.html#changes-in-compile-tasks)、`KotlinCompile`タスクはまだ、非推奨のKotlinプロパティ`classpath`を持っていたが、将来のリリースで削除されるだろうとしていた。現在、`KotlinCompile`タスクの`classpath`プロパティは、非推奨レベルが`error`に変更されている。すべてのコンパイルタスクは、コンパイルに必要なライブラリの一覧のため、`libraries`入力を使っている。
- Gradle Workes API経由で[kapt](https://kotlinlang.org/docs/kapt.html)を実行することを許可する、`kapt.use.worker.api`プロパティが削除された。デフォルトではKotlin 1.3.70から[kaptはGradle workersを使って](https://kotlinlang.org/docs/kapt.html#running-kapt-tasks-in-parallel)きており、この方法を守ることを推奨する。
- Kotlin 1.7.0で、[`kotlin.compiler.execution.strategy`プロパティのための非推奨ライフサイクルの開始がアナウンス](https://kotlinlang.org/docs/whatsnew17.html#deprecation-of-the-kotlin-compiler-execution-strategy-system-property)された。今回のリリースでこのプロパティが削除された。他の方法で[Kotlinコンパイラの実行戦略を定義する](https://kotlinlang.org/docs/gradle-compilation-and-caches.html#defining-kotlin-compiler-execution-strategy)方法を確認してほしい。
# 標準ライブラリ
## 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`にマージされたため、もはやビルドスクリプトでそれらを個別に宣言する必要がない。

::: note 
ビルドスクリプトで依存性として、明示的に`kotlin-stdlib-jdk7`と`kotlin-stdlib-jdk8`を宣言していた場合、`kotlin-stdlib`に置き換えるべきである。
:::
注意すべきは、標準ライブラリ成果物の異なるバージョンが混在することで、classの重複や不足を引き起こすことである。それを避けるため、Kotlin Gradleプラグインによって、[標準ライブラリのバージョンを揃える](https://kotlinlang.org/docs/whatsnew18.html#usage-of-the-latest-kotlin-stdlib-version-in-transitive-dependencies)のに役立つことができる。
## cbrt()
`cbrt()`関数は、`double`や`float`の実立方根を計算することができ、現在Stableである。
```Kotlin
import kotlin.math.*

fun main() {
    val num = 27
    val negNum = -num

    println("The cube root of ${num.toDouble()} is: " + 
            cbrt(num.toDouble())) // 3.0
    println("The cube root of ${negNum.toDouble()} is: " + 
            cbrt(negNum.toDouble())) // -3.0
}
```
## JavaとKotlin間でのTimeUnit変換
`kotlin.time`内の`toTimeUnit()`と`toDurationUnit()`関数が現在Stableである。
Kotlin 1.6.0でExperimentalとして導入されたが、これらの関数はKotlinとJavaの相互運用性を改善する。今ではJavaの`java.util.concurrent.TimeUnit`とKotlinの`kotlin.time.DurationUnit`間の変換を簡単にすることができる。これらの関数はJVMのみでサポートされている。
```Kotlin
import kotlin.time.*

// For use from Java
fun wait(timeout: Long, unit: TimeUnit) {
    val duration: Duration = timeout.toDuration(unit.toDurationUnit())
    ...
}
```
## 比較可能、減算可能なTimeMark
::: note warn
`TimeMarks`の新しい機能は[Experimental](https://kotlinlang.org/docs/components-stability.html#stability-levels-explained)であり、使うには`@OptIn(Experimental::class)`か`@ExperimentalTime`を使ってオプトインが必要である。
:::
Kotlin 1.8.0より前では、複数の`TimeMark`と**now**の間で計算したい場合、同時に一つの`TimeMark`において`elapsedNow()`を呼び出すだけだった。これにより、二つの`elapsedNow()`関数呼び出しを厳密に同時に実行することができないため、結果を比較することが困難だった。
これを解決するため、Kotlin 1.8.0では同じタイムソースから、`TimeMark`を減算、比較することができる。現在は、**now**を表す`TimeMark`インスタンスを生成し、それから他の`TimeMark`を減算することができる。このように、これらの計算から収集された結果が、お互いに相対的があることが保証されている。
```Kotlin
import kotlin.time.*
fun main() {
    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()

        // elapsed1とelapsed2の差は、二つのelapsedNow()呼び出しの間の経過時間に応じて異なる。
        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

        // 現在は、経過時間はmark3から相対的に計算され、固定値である。
        println("Measurement 2.${n + 1}: elapsed1=$elapsed1, " +
                "elapsed2=$elapsed2, diff=${elapsed1 - elapsed2}")
    }
    // TimeMarkをお互いに比較することも可能。
    // これはTrueである。mark2はmark1よりも後にキャプチャされたため。
    println(mark2 > mark1)
}
```
```
Measurement 1.1: elapsed1=500.718274ms, elapsed2=6.515158ms, diff=494.203116ms
Measurement 1.2: elapsed1=523.904389ms, elapsed2=23.334300ms, diff=500.570089ms
Measurement 1.3: elapsed1=523.975547ms, elapsed2=23.399769ms, diff=500.575778ms
Measurement 1.4: elapsed1=524.035870ms, elapsed2=23.459935ms, diff=500.575935ms

Measurement 2.1: elapsed1=525.623872ms, elapsed2=25.044030ms, diff=500.579842ms
Measurement 2.2: elapsed1=525.691691ms, elapsed2=25.111849ms, diff=500.579842ms
Measurement 2.3: elapsed1=525.809190ms, elapsed2=25.229348ms, diff=500.579842ms
Measurement 2.4: elapsed1=525.866802ms, elapsed2=25.286960ms, diff=500.579842ms
true
```
この新しい機能は、アニメーションの計算において、異なるフレームを表す複数の`TimeMark`間の差異を計算したり、比較したいときに、特に有用である。
## ディレクトリの再帰的なコピーと削除
::: note warn
`java.nio.file.Path`のためのこれらの新しい関数は[Experimental](https://kotlinlang.org/docs/components-stability.html#stability-levels-explained)である。それらを使うには、`@OptIn(kotlin.io.path.ExperimentalPathApi::class)`か`@kotlin.io.path.ExperimentalPathApi`でオプトインが必要である。あるいは`-opt-in=kotlin.io.path.ExperimentalPathApi`コンパイラオプションを使うことができる。
:::
`java.nio.file.Path`のための二つの新しい拡張関数、`copyToRecursively()`と`deleteRecursively()`が導入され、それらは再帰的に、
- ディレクトリとその内容を別の場所にコピー
- ディレクトリとその内容を削除
する。これらの機能はバックアップ処理の一部として非常に有用となりうる。
### エラーハンドリング
`copyToRecursively()`を使うとき、コピー中に例外が発生した場合に何が起こるべきか、`onError`ラムダ関数をオーバーロードすることによって、定義することができる。
```Kotlin
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`をセットすること。
```Kotlin
fun setUpEnvironment(projectDirectory: Path, fixtureName: String) {
    fixturesRoot.resolve(COMMON_FIXTURE_NAME)
        .copyToRecursively(projectDirectory, followLinks = false)
    fixturesRoot.resolve(fixtureName)
        .copyToRecursively(projectDirectory, followLinks = false,
          overwrite = true) // common fixtureにパッチをあてる
}
```
### カスタムコピー処理
コピーのためのカスタムロジックを定義するには、追加の引数として`copyAction`を持つオーバーロードを使う。`copyAction`を使うことで、例えば好ましい動作を持つ、ラムダ関数を提供することができる。
```Kotlin
sourceRoot.copyToRecursively(destinationRoot, followLinks = false) { source, target ->
    if (source.name.startsWith(".")) {
        CopyActionResult.SKIP_SUBTREE
    } else {
        source.copyToIgnoringExistingDirectory(target, followLinks = false)
        CopyActionResult.CONTINUE
    }
}
```
これらの拡張関数のより詳細な情報については、[APIリファレンス](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io.path/java.nio.file.-path/copy-to-recursively.html)を参照のこと。
## JavaのOptionalの拡張関数
[Kotlin 1.7.0](https://kotlinlang.org/docs/whatsnew17.html#new-experimental-extension-functions-for-java-optionals)で導入された拡張関数が、現在Stableである。これらの関数は、単にJavaにおけるOptionalクラスと連携する。それらはJVM上の`Optional`オブジェクトをアンラップし、変換するために使うことができ、Java APIとの連携をより簡潔にする。詳しくは[Kotlin 1.7.0の変更点](https://qiita.com/CuriosityKilledTheCat/items/d48ec2ff128ee8ef97dc#java%E3%81%AEoptional%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E6%96%B0%E3%81%97%E3%81%84%E5%AE%9F%E9%A8%93%E7%9A%84%E9%96%A2%E6%95%B0)を参照のこと。
## kotlin-reflectの性能改善
`kotlin-reflect`が今ではJVMターゲット1.8でコンパイルされているという事実を利用するため、Javaの`ClassValue`に対する内部的なキャッシュメカニズムを移行した。以前は`KClass`のみがキャッシュされていたが、現在は`KType`と`KDeclarationContainer`もキャッシュしている。これらの変更は、`typeOf()`を呼び出すとき、かなりの性能改善がもたらされる。
# ドキュメントの更新
Kotlinドキュメントにいくつかの注目に値する変更があった。
## 刷新と新しいページ
- [Gradle概要](https://kotlinlang.org/docs/gradle.html) - GradleビルドシステムでKotlinプロジェクトを構成、ビルドする方法、Kotlin Gradleプラグイン内の利用可能なコンパイラオプション、コンパイル、キャッシュについて学ぶ
- [JavaとKotlinのNullability](https://kotlinlang.org/docs/java-to-kotlin-nullability-guide.html) - JavaとKotlinで、おそらくNullの可能性がある変数を扱うアプローチの違いを確認する。
- [Lincheckガイド](https://kotlinlang.org/docs/lincheck-guide.html) - JVM上で並列アルゴリズムをテストするため、Lincheckフレームワークをセットアップして使う方法を学ぶ。
## 新規、更新チュートリアル
- [はじめてのGradleとKotlin/JVM](https://kotlinlang.org/docs/get-started-with-jvm-gradle-project.html) - IntelliJ IDEAとGradleを使ってコンソールアプリケーションを作る。
- [KtorとSQLDelightを使用したマルチプラットフォームアプリの作成](https://kotlinlang.org/docs/multiplatform-mobile-ktor-sqldelight.html) - Kotlin Multiplatform Mobileを使ってiOSとAndroidのためのモバイルアプリケーションを作る。
- [はじめてのKotlin Multiplatform Mobile](https://kotlinlang.org/docs/multiplatform-mobile-getting-started.html) - Kotlinでクロスプラットフォームモバイル開発について学び、AndroidとiOS両方で動作するアプリを作る。
# Kotlin 1.8.0のインストール
[IntelliJ IDEA](https://www.jetbrains.com/idea/download/) 2021.3, 2022.1, 2022.2は自動的にKotlinプラグインをバージョン1.8.0へのアップデート提案をする。IntelliJ IDEA　2022.3は将来のマイナーアップデートで、Kotlinプラグインの1.8.0バージョンがバンドルされるだろう。

::: note
IntelliJ IDEA 2022.3で、既存のプロジェクトをKotlin 1.8.0に移行するには、Kotlinバージョンを1.8.0に変更し、GradleまたはMavenプロジェクトを再インポートすること。
:::
Android Studio Electric Eel (221)とFlamingo (222)のために、Kotlinプラグインのバージョン1.8.0が将来のAndsroid Studioのアップデートで配信されるだろう。新しいコマンドラインコンパイラは、[GitHubリリースページ](https://github.com/JetBrains/kotlin/releases/tag/v1.8.0)でダウンロード可能である。
# Kotlin 1.8.0互換性ガイド
Kotlin 1.8.0は[機能リリース](https://kotlinlang.org/docs/kotlin-evolution.html#feature-releases-and-incremental-releases)であり、そのため以前の言語バージョンで書かれたコードと互換性が無い変更がもたらされている。[Kotlin 1.8.0互換性ガイド](https://kotlinlang.org/docs/compatibility-guide-18.html)内で、これらの変更の詳細な一覧を確認してほしい。