Kotlin 1.8.20の新機能
Kotlin 1.8.20がリリースされ、その主なハイライトは以下の通りです。
- Kotlin K2コンパイラの新しい更新
- 新しい実験的なKotlin/Wasmターゲット
- GradleでのJVMインクリメンタルコンパイルがデフォルトに
- Kotlin/Nativeターゲットの更新
- Kotlin MultiplatformにおけるGradle複合ビルドのプレビュー
- XcodeにおけるGradleエラー出力の改善
- 標準ライブラリにおける
AutoCloseable
インターフェースの実験的なサポート - 標準ライブラリにおけるBase64エンコーディングの実験的なサポート
これらの変更点の短い概要を、こちらの動画でもご確認いただけます。
IDEのサポート
Kotlin 1.8.20をサポートするKotlinプラグインは、以下のIDEで利用可能です。
IDE | サポートされているバージョン |
---|---|
IntelliJ IDEA | 2022.2.x, 2022.3.x, 2023.1.x |
Android Studio | Flamingo (222) |
DANGER
Kotlinのアーティファクトと依存関係を適切にダウンロードするには、Gradle設定を構成してMaven Centralリポジトリを使用してください。
Kotlin K2コンパイラの新しい更新
KotlinチームはK2コンパイラの安定化を継続しています。Kotlin 1.7.0のお知らせで述べたように、まだAlpha版です。今回のリリースでは、K2 Betaに向けたさらなる改善が導入されています。
この1.8.20リリースから、Kotlin K2コンパイラは以下のようになります。
- シリアライズプラグインのプレビュー版が利用可能です。
- JS IRコンパイラのAlphaサポートを提供します。
- 新しい言語バージョン、Kotlin 2.0の将来のリリースを導入します。
新しいコンパイラとその利点については、以下の動画で詳しくご紹介しています。
Kotlin K2コンパイラを有効にする方法
Kotlin K2コンパイラを有効にしてテストするには、新しい言語バージョンを以下のコンパイラオプションとともに使用してください。
-language-version 2.0
build.gradle(.kts)
ファイルで指定できます。
kotlin {
sourceSets.all {
languageSettings {
languageVersion = "2.0"
}
}
}
以前の-Xuse-k2
コンパイラオプションは非推奨になりました。
DANGER
新しいK2コンパイラのAlpha版は、JVMおよびJS IRプロジェクトでのみ動作します。Kotlin/Nativeや任意のマルチプラットフォームプロジェクトはまだサポートしていません。
新しいK2コンパイラに関するフィードバックをお願いします
皆様からのフィードバックを心よりお待ちしております!
- Kotlin SlackでK2開発者に直接フィードバックを提供してください – 招待を取得し、#k2-early-adoptersチャンネルに参加してください。
- 新しいK2コンパイラで直面した問題は、課題トラッカーに報告してください。
- K2の使用に関する匿名データをJetBrainsが収集できるように、使用統計を送信オプションを有効にしてください。
言語
Kotlinが進化を続ける中、1.8.20では新しい言語機能のプレビュー版が導入されます。
Enumクラスのvalues
関数の現代的で高性能な代替
DANGER
この機能は実験的です。いつでも削除または変更される可能性があります。オプトインが必要です(詳細は下記参照)。評価目的でのみ使用してください。この機能に関するフィードバックはYouTrackまでお寄せください。
Enumクラスには、定義されたenum定数の配列を返す合成values()
関数があります。しかし、配列を使用するとKotlinやJavaで隠れたパフォーマンス問題につながる可能性があります。さらに、ほとんどのAPIはコレクションを使用しており、最終的な変換が必要です。これらの問題を解決するために、Enumクラスにentries
プロパティを導入しました。これはvalues()
関数の代わりに使用すべきです。呼び出されたとき、entries
プロパティは事前に割り当てられた変更不可能なenum定数のリストを返します。
TIP
values()
関数は引き続きサポートされていますが、代わりにentries
プロパティを使用することをお勧めします。
enum class Color(val colorName: String, val rgb: String) {
RED("Red", "#FF0000"),
ORANGE("Orange", "#FF7F00"),
YELLOW("Yellow", "#FFFF00")
}
@OptIn(ExperimentalStdlibApi::class)
fun findByRgb(rgb: String): Color? = Color.entries.find { it.rgb == rgb }
entries
プロパティを有効にする方法
この機能を試すには、@OptIn(ExperimentalStdlibApi)
でオプトインし、-language-version 1.9
コンパイラオプションを有効にしてください。Gradleプロジェクトでは、build.gradle(.kts)
ファイルに以下を追加することで行えます。
tasks
.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask<*>>()
.configureEach {
compilerOptions
.languageVersion
.set(
org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
)
}
tasks
.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask.class)
.configureEach {
compilerOptions.languageVersion =
org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
TIP
IntelliJ IDEA 2023.1以降、この機能をオプトインしている場合、適切なIDEインスペクションによりvalues()
からentries
への変換が通知され、クイックフィックスが提供されます。
この提案に関する詳細については、KEEPノートを参照してください。
データクラスとの対称性のためのデータオブジェクトのプレビュー
データオブジェクトを使用すると、シングルトンセマンティクスとクリーンなtoString()
表現を持つオブジェクトを宣言できます。このスニペットでは、data
キーワードをオブジェクト宣言に追加すると、toString()
出力の可読性がどのように向上するかを確認できます。
package org.example
object MyObject
data object MyDataObject
fun main() {
println(MyObject) // org.example.MyObject@1f32e575
println(MyDataObject) // MyDataObject
}
特にsealed
階層(sealed class
やsealed interface
階層など)では、data objects
はdata class
宣言とともに便利に利用できるため、非常に適しています。このスニペットでは、EndOfFile
を通常のobject
ではなくdata object
として宣言することで、手動でオーバーライドすることなく美しいtoString
を取得できます。これにより、付随するデータクラスの定義との対称性が維持されます。
sealed interface ReadResult
data class Number(val number: Int) : ReadResult
data class Text(val text: Int) : ReadResult
data object EndOfFile : ReadResult
fun main() {
println(Number(7)) // Number(number=7)
println(EndOfFile) // EndOfFile
}
データオブジェクトのセマンティクス
Kotlin 1.7.20での最初のプレビュー版以来、データオブジェクトのセマンティクスは洗練されてきました。コンパイラは現在、データオブジェクトのためにいくつかの便利な関数を自動的に生成します。
toString
データオブジェクトのtoString()
関数は、オブジェクトのシンプルな名前を返します。
data object MyDataObject {
val x: Int = 3
}
fun main() {
println(MyDataObject) // MyDataObject
}
equals
と hashCode
data object
のequals()
関数は、data object
の型を持つすべてのオブジェクトが等しいと見なされることを保証します。ほとんどの場合、実行時にはdata object
の単一のインスタンスしか持ちません(結局のところ、data object
はシングルトンを宣言します)。しかし、同じ型の別のオブジェクトが実行時(例えば、java.lang.reflect
を介したプラットフォームリフレクション、またはこのAPIを内部で利用するJVMシリアライゼーションライブラリの使用によって)に生成されるというエッジケースでは、これによりオブジェクトが等しいものとして扱われることが保証されます。
data object
は、参照ではなく(===
演算子ではなく)構造的に(==
演算子を使用して)のみ比較するようにしてください。これにより、実行時にdata object
のインスタンスが複数存在する場合の落とし穴を回避できます。次のスニペットは、この特定のエッジケースを示しています。
import java.lang.reflect.Constructor
data object MySingleton
fun main() {
val evilTwin = createInstanceViaReflection()
println(MySingleton) // MySingleton
println(evilTwin) // MySingleton
// Even when a library forcefully creates a second instance of MySingleton, its `equals` method returns true:
println(MySingleton == evilTwin) // true
// Do not compare data objects via ===.
println(MySingleton === evilTwin) // false
}
fun createInstanceViaReflection(): MySingleton {
// Kotlin reflection does not permit the instantiation of data objects.
// This creates a new MySingleton instance "by force" (i.e., Java platform reflection)
// Don't do this yourself!
return (MySingleton.javaClass.declaredConstructors[0].apply { isAccessible = true } as Constructor<MySingleton>).newInstance()
}
生成されるhashCode()
関数の動作はequals()
関数の動作と一貫しており、data object
のすべての実行時インスタンスが同じハッシュコードを持つようになっています。
データオブジェクトにはcopy
およびcomponentN
関数はありません
data object
とdata class
宣言はしばしば一緒に使用され、いくつかの類似点がありますが、data object
に対しては生成されない関数がいくつかあります。
data object
宣言はシングルトンオブジェクトとして使用されることを意図しているため、copy()
関数は生成されません。シングルトンパターンは、クラスのインスタンス化を単一のインスタンスに制限しており、そのインスタンスのコピーが作成されることを許可すると、その制限に違反することになります。
また、data class
とは異なり、data object
にはデータプロパティがありません。そのようなオブジェクトを分解しようとすることは意味がないため、componentN()
関数は生成されません。
この機能に関するフィードバックは、YouTrackまでお寄せください。
データオブジェクトプレビューを有効にする方法
この機能を試すには、-language-version 1.9
コンパイラオプションを有効にしてください。Gradleプロジェクトでは、build.gradle(.kts)
ファイルに以下を追加することで行えます。
tasks
.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask<*>>()
.configureEach {
compilerOptions
.languageVersion
.set(
org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
)
}
tasks
.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask.class)
.configureEach {
compilerOptions.languageVersion =
org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
インラインクラスのボディを持つセカンダリコンストラクタに関する制限の緩和のプレビュー
DANGER
この機能は実験的です。いつでも削除または変更される可能性があります。オプトインが必要です(詳細は下記参照)。評価目的でのみ使用してください。この機能に関するフィードバックはYouTrackまでお寄せください。
Kotlin 1.8.20では、インラインクラスにおけるボディを持つセカンダリコンストラクタの使用に関する制限が緩和されます。
インラインクラスはこれまで、明確な初期化セマンティクスを持つために、init
ブロックやセカンダリコンストラクタなしのpublicなプライマリコンストラクタのみを許可していました。その結果、基底値をカプセル化したり、制約付きの値を表現するインラインクラスを作成したりすることが不可能でした。
これらの問題は、Kotlin 1.4.30でinit
ブロックの制限が解除されたときに修正されました。今回、さらに一歩進んで、プレビューモードでボディを持つセカンダリコンストラクタを許可します。
@JvmInline
value class Person(private val fullName: String) {
// Kotlin 1.4.30以降許可:
init {
check(fullName.isNotBlank()) {
"Full name shouldn't be empty"
}
}
// Kotlin 1.8.20以降プレビューで利用可能:
constructor(name: String, lastName: String) : this("$name $lastName") {
check(lastName.isNotBlank()) {
"Last name shouldn't be empty"
}
}
}
ボディを持つセカンダリコンストラクタを有効にする方法
この機能を試すには、-language-version 1.9
コンパイラオプションを有効にしてください。Gradleプロジェクトでは、build.gradle(.kts)
に以下を追加することで行えます。
tasks
.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask<*>>()
.configureEach {
compilerOptions
.languageVersion
.set(
org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
)
}
tasks
.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask.class)
.configureEach {
compilerOptions.languageVersion =
org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
この機能をぜひお試しいただき、Kotlin 1.9.0でデフォルトにできるよう、YouTrackにすべてのレポートを提出していただくことをお勧めします。
Kotlinインラインクラスの開発について詳しくは、こちらのKEEPをご覧ください。
新しいKotlin/Wasmターゲット
このリリースで、Kotlin/Wasm (Kotlin WebAssembly)は実験的機能となります。KotlinチームはWebAssemblyを有望な技術と考えており、Kotlinのすべての利点を活用できるより良い方法を見つけたいと考えています。
WebAssemblyのバイナリフォーマットは、独自の仮想マシンを使用して実行されるため、プラットフォームに依存しません。ほとんどすべてのモダンブラウザはすでにWebAssembly 1.0をサポートしています。WebAssemblyを実行するための環境を設定するには、Kotlin/Wasmがターゲットとする実験的なガベージコレクションモードを有効にするだけです。詳細な手順はこちらで確認できます: Kotlin/Wasmを有効にする方法。
新しいKotlin/Wasmターゲットの以下の利点を強調したいと思います。
- Kotlin/WasmはLLVMを使用する必要がないため、
wasm32
Kotlin/Nativeターゲットと比較してコンパイル速度が高速です。 - Wasmガベージコレクションのおかげで、
wasm32
ターゲットと比較してJSとの相互運用性およびブラウザとの統合が容易です。 - Wasmはコンパクトで解析しやすいバイトコードを持っているため、Kotlin/JSやJavaScriptと比較してアプリケーションの起動が高速になる可能性があります。
- Wasmは静的型付け言語であるため、Kotlin/JSやJavaScriptと比較してアプリケーションのランタイムパフォーマンスが向上します。
1.8.20リリースから、実験的なプロジェクトでKotlin/Wasmを使用できるようになります。Kotlin/Wasm用にKotlin標準ライブラリ(stdlib
)とテストライブラリ(kotlin.test
)をすぐに利用できるように提供します。IDEのサポートは将来のリリースで追加される予定です。
このYouTube動画でKotlin/Wasmについて詳しく学ぶ。
Kotlin/Wasmを有効にする方法
Kotlin/Wasmを有効にしてテストするには、build.gradle.kts
ファイルを更新してください。
plugins {
kotlin("multiplatform") version "1.8.20"
}
kotlin {
wasm {
binaries.executable()
browser {
}
}
sourceSets {
val commonMain by getting
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val wasmMain by getting
val wasmTest by getting
}
}
TIP
Kotlin/Wasmの例を含むGitHubリポジリをご覧ください。
Kotlin/Wasmプロジェクトを実行するには、ターゲット環境の設定を更新する必要があります。
Kotlin/Wasmに関するフィードバックをお願いします
皆様からのフィードバックを心よりお待ちしております!
- Kotlin Slackで開発者に直接フィードバックを提供してください – 招待を取得し、#webassemblyチャンネルに参加してください。
- Kotlin/Wasmで直面した問題は、このYouTrack課題に報告してください。
Kotlin/JVM
Kotlin 1.8.20では、Java合成プロパティ参照のプレビューと、kaptスタブ生成タスクにおけるJVM IRバックエンドのサポートがデフォルトで有効になります。
Java合成プロパティ参照のプレビュー
Kotlin 1.8.20では、Java合成プロパティへの参照を作成する機能が導入されました。例えば、以下のJavaコードの場合です。
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
Kotlinではこれまでも、age
が合成プロパティであるperson.age
と書くことができました。今回、Person::age
やperson::age
への参照も作成できるようになりました。name
についても同様です。
val persons = listOf(Person("Jack", 11), Person("Sofie", 12), Person("Peter", 11))
persons
// Java合成プロパティへの参照を呼び出す:
.sortedBy(Person::age)
// Kotlinプロパティ構文を介してJavaゲッターを呼び出す:
.forEach { person -> println(person.name) }
Java合成プロパティ参照を有効にする方法
この機能を試すには、-language-version 1.9
コンパイラオプションを有効にしてください。Gradleプロジェクトでは、build.gradle(.kts)
に以下を追加することで行えます。
tasks
.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask<*>>()
.configureEach {
compilerOptions
.languageVersion
.set(
org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
)
}
tasks
.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask.class)
.configureEach {
compilerOptions.languageVersion =
org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
kaptスタブ生成タスクにおけるJVM IRバックエンドのサポートがデフォルトに
Kotlin 1.7.20で、kaptスタブ生成タスクにおけるJVM IRバックエンドのサポートを導入しました。このリリースから、このサポートはデフォルトで動作します。有効にするためにgradle.properties
にkapt.use.jvm.ir=true
を指定する必要はなくなりました。この機能に関するフィードバックはYouTrackまでお寄せください。
Kotlin/Native
Kotlin 1.8.20には、サポートされるKotlin/Nativeターゲットの変更、Objective-Cとの相互運用性、CocoaPods Gradleプラグインの改善などが含まれています。
- Kotlin/Nativeターゲットの更新
- レガシーメモリマネージャーの非推奨化
@import
ディレクティブを持つObjective-Cヘッダーのサポート- Cocoapods Gradleプラグインにおけるリンクオンリーモードのサポート
- UIKitでのObjective-C拡張をクラスメンバーとしてインポート
- コンパイラにおけるコンパイラキャッシュ管理の再実装
- Cocoapods Gradleプラグインにおける
useLibraries()
の非推奨化
Kotlin/Nativeターゲットの更新
Kotlinチームは、Kotlin/Nativeがサポートするターゲットのリストを見直し、それらをティアに分割し、Kotlin 1.8.20から一部を非推奨とすることを決定しました。サポートされているターゲットと非推奨のターゲットの完全なリストについては、Kotlin/Nativeターゲットサポートセクションを参照してください。
以下のターゲットはKotlin 1.8.20で非推奨となり、1.9.20で削除されます。
iosArm32
watchosX86
wasm32
mingwX86
linuxArm32Hfp
linuxMips32
linuxMipsel32
残りのターゲットについては、Kotlin/Nativeコンパイラでターゲットがどれだけサポートされ、テストされているかに応じて、3つのサポートティアが設けられています。ターゲットは異なるティアに移動する可能性があります。例えば、Kotlin Multiplatformにとって重要であるため、将来的にはiosArm64
を完全にサポートするよう最善を尽くします。
ライブラリ作者であれば、これらのターゲットティアは、CIツールでどのターゲットをテストし、どのターゲットをスキップするかを決定するのに役立ちます。Kotlinチームも、kotlinx.coroutinesのような公式Kotlinライブラリを開発する際に同じアプローチを使用します。
これらの変更の理由について詳しくは、ブログ記事をご覧ください。
レガシーメモリマネージャーの非推奨化
1.8.20から、レガシーメモリマネージャーは非推奨となり、1.9.20で削除されます。新しいメモリマネージャーは1.7.20でデフォルトで有効になり、さらなる安定性向上とパフォーマンス改善が継続的に行われています。
レガシーメモリマネージャーをまだ使用している場合は、gradle.properties
からkotlin.native.binary.memoryModel=strict
オプションを削除し、必要な変更を行うために移行ガイドに従ってください。
新しいメモリマネージャーはwasm32
ターゲットをサポートしていません。このターゲットもこのリリースから非推奨となり、1.9.20で削除されます。
@import
ディレクティブを持つObjective-Cヘッダーのサポート
DANGER
この機能は実験的です。いつでも削除または変更される可能性があります。オプトインが必要です(詳細は下記参照)。評価目的でのみ使用してください。この機能に関するフィードバックはYouTrackまでお寄せください。
Kotlin/Nativeは、@import
ディレクティブを持つObjective-Cヘッダーをインポートできるようになりました。この機能は、自動生成されたObjective-Cヘッダーを持つSwiftライブラリや、Swiftで書かれたCocoaPods依存関係のクラスを使用する場合に役立ちます。
以前は、cinteropツールは@import
ディレクティブを介してObjective-Cモジュールに依存するヘッダーを解析できませんでした。これは、-fmodules
オプションのサポートが不足していたためです。
Kotlin 1.8.20から、@import
を持つObjective-Cヘッダーを使用できるようになりました。そのためには、定義ファイルで-fmodules
オプションをcompilerOpts
としてコンパイラに渡します。CocoaPods統合を使用している場合は、pod()
関数の設定ブロックでcinteropオプションを次のように指定します。
kotlin {
ios()
cocoapods {
summary = "CocoaPods test library"
homepage = "https://github.com/JetBrains/kotlin"
ios.deploymentTarget = "13.5"
pod("PodName") {
extraOpts = listOf("-compiler-option", "-fmodules")
}
}
}
これは待ち望まれていた機能であり、将来のリリースでデフォルトにできるよう、YouTrackでのフィードバックをお待ちしております。
Cocoapods Gradleプラグインにおけるリンクオンリーモードのサポート
Kotlin 1.8.20では、cinteropバインディングを生成することなく、動的フレームワークを持つPod依存関係をリンク専用として使用できます。これは、cinteropバインディングがすでに生成されている場合に便利です。
ライブラリとアプリの2つのモジュールを持つプロジェクトを考えてみましょう。ライブラリはPodに依存していますが、フレームワークを生成せず、.klib
のみを生成します。アプリはライブラリに依存し、動的フレームワークを生成します。この場合、このフレームワークをライブラリが依存するPodとリンクさせる必要がありますが、cinteropバインディングはライブラリ用にすでに生成されているため必要ありません。
この機能を有効にするには、Podへの依存関係を追加する際にlinkOnly
オプションまたはビルダプロパティを使用します。
cocoapods {
summary = "CocoaPods test library"
homepage = "https://github.com/JetBrains/kotlin"
pod("Alamofire", linkOnly = true) {
version = "5.7.0"
}
}
NOTE
このオプションを静的フレームワークで使用すると、Podは静的フレームワークのリンクには使用されないため、Podの依存関係が完全に削除されます。
UIKitでObjective-C拡張をクラスメンバーとしてインポート
Xcode 14.1以降、Objective-Cクラスの一部のメソッドがカテゴリメンバーに移動されました。これにより、異なるKotlin APIが生成され、これらのメソッドはメソッドではなくKotlin拡張としてインポートされるようになりました。
UIKitを使用してメソッドをオーバーライドする際に、これにより問題が発生した可能性があります。例えば、KotlinでUIView
をサブクラス化する際にdrawRect()
やlayoutSubviews()
メソッドをオーバーライドすることが不可能になりました。
1.8.20以降、NSView
およびUIView
クラスと同じヘッダーで宣言されているカテゴリメンバーは、これらのクラスのメンバーとしてインポートされます。これにより、NSView
およびUIView
からサブクラス化するメソッドは、他のメソッドと同様に簡単にオーバーライドできます。
すべてが順調に進めば、すべてのObjective-Cクラスに対してこの動作をデフォルトで有効にする予定です。
コンパイラにおけるコンパイラキャッシュ管理の再実装
コンパイラキャッシュの進化を加速させるため、コンパイラキャッシュ管理をKotlin GradleプラグインからKotlin/Nativeコンパイラに移動しました。これにより、コンパイル時間やコンパイラキャッシュの柔軟性に関するものを含め、いくつかの重要な改善作業のブロックが解除されました。
問題が発生し、以前の動作に戻す必要がある場合は、kotlin.native.cacheOrchestration=gradle
Gradleプロパティを使用してください。
これに関するフィードバックは、YouTrackまでお寄せください。
Cocoapods GradleプラグインにおけるuseLibraries()
の非推奨化
Kotlin 1.8.20では、静的ライブラリ向けCocoaPods統合で使用されるuseLibraries()
関数の非推奨化サイクルが開始されます。
静的ライブラリを含むPodへの依存を許可するためにuseLibraries()
関数を導入しました。しかし、時間の経過とともに、このケースは非常に稀になりました。ほとんどのPodはソースで配布されており、Objective-CフレームワークやXCFrameworksがバイナリ配布の一般的な選択肢となっています。
この関数はあまり使われておらず、Kotlin CocoaPods Gradleプラグインの開発を複雑にする問題を引き起こすため、非推奨とすることを決定しました。
フレームワークとXCFrameworksに関する詳細については、最終的なネイティブバイナリをビルドするを参照してください。
Kotlin Multiplatform
Kotlin 1.8.20では、Kotlin Multiplatformに対する以下の更新により、開発者エクスペリエンスの向上を目指しています。
ソースセット階層への新しいアプローチ
DANGER
ソースセット階層への新しいアプローチは実験的です。将来のKotlinリリースで予告なく変更される可能性があります。オプトインが必要です(詳細は下記参照)。YouTrackでのフィードバックをお待ちしております。
Kotlin 1.8.20では、マルチプラットフォームプロジェクトのソースセット階層を設定する新しい方法として、デフォルトターゲット階層が提供されます。この新しいアプローチは、設計上の欠陥を持つios
のようなターゲットショートカットを置き換えることを目的としています。
デフォルトターゲット階層の背後にある考え方はシンプルです。プロジェクトがコンパイルするすべてのターゲットを明示的に宣言すると、Kotlin Gradleプラグインが指定されたターゲットに基づいて共有ソースセットを自動的に作成します。
プロジェクトをセットアップする
シンプルなマルチプラットフォームモバイルアプリの例を考えてみましょう。
@OptIn(ExperimentalKotlinGradlePluginApi::class)
kotlin {
// デフォルトターゲット階層を有効にする:
targetHierarchy.default()
android()
iosArm64()
iosSimulatorArm64()
}
デフォルトターゲット階層は、可能なすべてのターゲットとそれらの共有ソースセットのテンプレートと考えることができます。コード内で最終的なターゲットandroid
、iosArm64
、iosSimulatorArm64
を宣言すると、Kotlin Gradleプラグインはテンプレートから適切な共有ソースセットを見つけて作成します。結果として得られる階層は次のようになります。
緑色のソースセットは実際に作成されプロジェクトに存在しますが、デフォルトテンプレートの灰色のソースセットは無視されます。ご覧のとおり、Kotlin Gradleプラグインは、例えばwatchos
ソースセットを作成していません。これは、プロジェクトにwatchOSターゲットがないためです。
watchosArm64
のようなwatchOSターゲットを追加すると、watchos
ソースセットが作成され、apple
、native
、common
ソースセットからのコードもwatchosArm64
にコンパイルされます。
デフォルトターゲット階層の完全なスキームは、ドキュメントで確認できます。
NOTE
この例では、apple
とnative
ソースセットはiosArm64
とiosSimulatorArm64
ターゲットにのみコンパイルされます。そのため、その名前にもかかわらず、完全なiOS APIにアクセスできます。これはnative
のようなソースセットにとっては直感に反するかもしれません。なぜなら、すべてのネイティブターゲットで利用可能なAPIのみがこのソースセットでアクセスできると予想されるからです。この動作は将来変更される可能性があります。
なぜショートカットを置き換えるのか
ソースセット階層を作成することは、冗長でエラーが発生しやすく、初心者には優しくありませんでした。以前の解決策は、階層の一部を自動的に作成するios
のようなショートカットを導入することでした。しかし、ショートカットの使用には大きな設計上の欠陥があることが判明しました。それは変更が難しいということです。
例えば、ios
ショートカットを考えてみましょう。これはiosArm64
とiosX64
ターゲットのみを作成するため、混乱を招き、iosSimulatorArm64
ターゲットも必要とするM1ベースのホストで作業する際に問題につながる可能性があります。しかし、iosSimulatorArm64
ターゲットを追加することは、ユーザープロジェクトにとって非常に破壊的な変更となる可能性があります。
iosMain
ソースセットで使用されるすべての依存関係はiosSimulatorArm64
ターゲットをサポートしている必要があります。そうでない場合、依存関係の解決に失敗します。- 新しいターゲットを追加すると、
iosMain
で使用されている一部のネイティブAPIが消える可能性があります(ただし、iosSimulatorArm64
の場合にはほとんどありません)。 - IntelベースのMacBookで小さな個人プロジェクトを作成している場合など、この変更自体が必要ない場合もあります。
ショートカットが階層設定の問題を解決しないことが明らかになったため、ある時点で新しいショートカットの追加を停止しました。
デフォルトターゲット階層は一見するとショートカットに似ているかもしれませんが、決定的な違いがあります。それは、ユーザーがターゲットのセットを明示的に指定する必要があるということです。このセットは、プロジェクトがどのようにコンパイルされ、公開され、依存関係の解決に参加するかを定義します。このセットは固定されているため、Kotlin Gradleプラグインからのデフォルト設定の変更は、エコシステムに与える影響が大幅に少なくなり、ツール支援による移行の提供がはるかに容易になります。
デフォルト階層を有効にする方法
この新機能は実験的です。Kotlin Gradleビルドスクリプトの場合、@OptIn(ExperimentalKotlinGradlePluginApi::class)
でオプトインする必要があります。
詳細については、階層型プロジェクト構造を参照してください。
フィードバックを残す
これはマルチプラットフォームプロジェクトにとって重要な変更です。さらに改善するため、フィードバックをお寄せください。
Kotlin MultiplatformにおけるGradle複合ビルドサポートのプレビュー
NOTE
この機能は、Kotlin Gradleプラグイン1.8.20以降、Gradleビルドでサポートされています。IDEサポートについては、IntelliJ IDEA 2023.1 Beta 2 (231.8109.2)以降と、任意のKotlin IDEプラグインがインストールされたKotlin Gradleプラグイン1.8.20を使用してください。
1.8.20から、Kotlin MultiplatformはGradle複合ビルドをサポートします。複合ビルドを使用すると、別々のプロジェクトまたは同じプロジェクトの一部を単一のビルドに含めることができます。
いくつかの技術的な課題のため、Kotlin MultiplatformでのGradle複合ビルドの使用は部分的にしかサポートされていませんでした。Kotlin 1.8.20には、より幅広いプロジェクトで機能するはずの改善されたサポートのプレビューが含まれています。これを試すには、gradle.properties
に以下のオプションを追加してください。
kotlin.mpp.import.enableKgpDependencyResolution=true
このオプションは、新しいインポートモードのプレビューを有効にします。複合ビルドのサポートに加えて、インポートをより安定させるための主要なバグ修正と改善が含まれているため、マルチプラットフォームプロジェクトでのよりスムーズなインポートエクスペリエンスを提供します。
既知の問題
これはまださらなる安定化が必要なプレビューバージョンであり、インポート中にいくつかの問題に遭遇する可能性があります。Kotlin 1.8.20の最終リリース前に修正を予定している既知の問題は以下の通りです。
- IntelliJ IDEA 2023.1 EAP向けにはまだKotlin 1.8.20プラグインが利用できません。それにもかかわらず、Kotlin Gradleプラグインのバージョンを1.8.20に設定し、このIDEで複合ビルドを試すことは可能です。
- プロジェクトに
rootProject.name
が指定されたビルドが含まれている場合、複合ビルドがKotlinメタデータの解決に失敗する可能性があります。回避策と詳細については、このYouTrack課題を参照してください。
ぜひお試しいただき、Kotlin 1.9.0でデフォルトにできるよう、YouTrackにすべてのレポートを提出していただくことをお勧めします。
XcodeにおけるGradleエラー出力の改善
Xcodeでマルチプラットフォームプロジェクトをビルドする際に問題が発生した場合、「Command PhaseScriptExecution failed with a nonzero exit code」エラーに遭遇したことがあるかもしれません。このメッセージはGradleの呼び出しが失敗したことを示していますが、問題の特定にはあまり役立ちません。
Kotlin 1.8.20から、XcodeはKotlin/Nativeコンパイラからの出力を解析できるようになりました。さらに、Gradleビルドが失敗した場合、Xcodeで根本原因の例外からの追加のエラーメッセージが表示されます。ほとんどの場合、これにより根本的な問題を特定するのに役立ちます。
この新しい動作は、Xcode統合のための標準的なGradleタスク(マルチプラットフォームプロジェクトのiOSフレームワークをXcodeのiOSアプリケーションに接続できるembedAndSignAppleFrameworkForXcode
など)でデフォルトで有効になります。また、kotlin.native.useXcodeMessageStyle
Gradleプロパティを使用して有効(または無効)にすることもできます。
Kotlin/JavaScript
Kotlin 1.8.20では、TypeScript定義の生成方法が変更されます。また、デバッグエクスペリエンスを向上させるための変更も含まれています。
GradleプラグインからのDukat統合の削除
Kotlin 1.8.20では、Kotlin/JavaScript Gradleプラグインから実験的なDukat統合を削除しました。Dukat統合は、TypeScript宣言ファイル(.d.ts
)をKotlin外部宣言に自動変換する機能をサポートしていました。
代わりに、Dukatツールを使用して、TypeScript宣言ファイル(.d.ts
)をKotlin外部宣言に変換することは引き続き可能です。
DANGER
Dukatツールは実験的です。いつでも削除または変更される可能性があります。
ソースマップ内のKotlin変数名と関数名
デバッグを支援するため、Kotlinコードで宣言した変数名と関数名をソースマップに追加する機能が導入されました。1.8.20以前は、これらはソースマップで利用できなかったため、デバッガーでは常に生成されたJavaScriptの変数名と関数名が表示されていました。
追加される内容は、Gradleファイルのbuild.gradle.kts
でsourceMapNamesPolicy
を使用するか、-source-map-names-policy
コンパイラオプションを使用して設定できます。以下の表に可能な設定を示します。
設定 | 説明 | 出力例 |
---|---|---|
simple-names | 変数名と単純な関数名が追加されます。(デフォルト) | main |
fully-qualified-names | 変数名と完全修飾関数名が追加されます。 | com.example.kjs.playground.main |
no | 変数名や関数名は追加されません。 | N/A |
build.gradle.kts
ファイルでの設定例を以下に示します。
tasks.withType<org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile>().configureEach {
compilercompileOptions.sourceMapNamesPolicy.set(org.jetbrains.kotlin.gradle.dsl.JsSourceMapNamesPolicy.SOURCE_MAP_NAMES_POLICY_FQ_NAMES) // or SOURCE_MAP_NAMES_POLICY_NO, or SOURCE_MAP_NAMES_POLICY_SIMPLE_NAMES
}
Chromiumベースのブラウザで提供されているようなデバッグツールは、ソースマップから元のKotlin名を取得して、スタックトレースの可読性を向上させることができます。快適なデバッグをお楽しみください!
DANGER
ソースマップへの変数名と関数名の追加は実験的です。いつでも削除または変更される可能性があります。
TypeScript定義ファイルの生成へのオプトイン
以前は、実行可能ファイル(binaries.executable()
)を生成するプロジェクトがある場合、Kotlin/JS IRコンパイラは@JsExport
でマークされたすべてのトップレベル宣言を収集し、.d.ts
ファイルにTypeScript定義を自動的に生成していました。
これはすべてのプロジェクトで有用であるわけではないため、Kotlin 1.8.20で動作を変更しました。TypeScript定義を生成したい場合は、Gradleビルドファイルで明示的にこれを設定する必要があります。js
セクションのbuild.gradle.kts.file
にgenerateTypeScriptDefinitions()
を追加してください。例を示します。
kotlin {
js {
binaries.executable()
browser {
}
generateTypeScriptDefinitions()
}
}
DANGER
TypeScript定義(d.ts
)の生成は実験的です。いつでも削除または変更される可能性があります。
Gradle
Kotlin 1.8.20は、マルチプラットフォームプラグインのいくつかの特殊なケースを除き、Gradle 6.8から7.6までと完全に互換性があります。最新のGradleリリースまでのバージョンを使用することも可能ですが、その場合、非推奨の警告に遭遇したり、一部の新しいGradle機能が動作しない可能性があることに留意してください。
このバージョンでは、以下の変更が導入されています。
- Gradleプラグインバージョンの新しいアラインメント
- GradleでのJVMインクリメンタルコンパイルがデフォルトに
- コンパイルタスク出力の正確なバックアップ
- すべてのGradleバージョンにおけるKotlin/JVMタスクの遅延作成
- コンパイルタスクの
destinationDirectory
の非デフォルトロケーション - コンパイラ引数をHTTP統計サービスに報告しないオプション
Gradleプラグインバージョンの新しいアラインメント
Gradleは、連携して動作する必要がある依存関係が常にバージョンを揃える方法を提供します。Kotlin 1.8.20もこのアプローチを採用しました。デフォルトで動作するため、有効にするために設定を変更したり更新したりする必要はありません。さらに、Kotlin Gradleプラグインの推移的依存関係を解決するためのこの回避策に頼る必要もなくなりました。
この機能に関するフィードバックは、YouTrackまでお寄せください。
GradleでのJVMインクリメンタルコンパイルがデフォルトに
Kotlin 1.7.0から利用可能であったインクリメンタルコンパイルの新しいアプローチが、デフォルトで動作するようになりました。有効にするためにgradle.properties
にkotlin.incremental.useClasspathSnapshot=true
を指定する必要はなくなりました。
これに関するフィードバックをお待ちしております。YouTrackに課題を提出できます。
コンパイルタスク出力の正確なバックアップ
DANGER
コンパイルタスク出力の正確なバックアップは実験的です。使用するには、gradle.properties
にkotlin.compiler.preciseCompilationResultsBackup=true
を追加してください。この機能に関するフィードバックはYouTrackまでお寄せください。
Kotlin 1.8.20から、正確なバックアップを有効にできるようになりました。これにより、インクリメンタルコンパイルでKotlinが再コンパイルするクラスのみがバックアップされます。完全バックアップと正確なバックアップの両方が、コンパイルエラー後にビルドを再びインクリメンタルに実行するのに役立ちます。正確なバックアップは、完全バックアップと比較してビルド時間を節約します。完全バックアップは、大規模なプロジェクトや、多くのタスクがバックアップを作成している場合、特にプロジェクトが低速なHDD上にある場合に、かなりのビルド時間を要する可能性があります。
この最適化は実験的です。gradle.properties
ファイルにkotlin.compiler.preciseCompilationResultsBackup
Gradleプロパティを追加することで有効にできます。
kotlin.compiler.preciseCompilationResultsBackup=true
JetBrainsでの正確なバックアップ使用例
以下のチャートでは、完全バックアップと比較した正確なバックアップの使用例を確認できます。
最初の2つのチャートは、Kotlinプロジェクトにおける正確なバックアップがKotlin Gradleプラグインのビルドにどのように影響するかを示しています。
- 多くのモジュールが依存するモジュールに、小さなABI変更(新しいpublicメソッドの追加)を行った後。
- 他のモジュールが依存しないモジュールに、小さな非ABI変更(プライベート関数の追加)を行った後。
3番目のチャートは、Spaceプロジェクトにおける正確なバックアップが、多くのモジュールが依存するKotlin/JSモジュールに小さな非ABI変更(プライベート関数の追加)を行った後のWebフロントエンドのビルドにどのように影響するかを示しています。
これらの測定はApple M1 Max CPUを搭載したコンピュータで実行されました。異なるコンピュータではわずかに異なる結果が得られます。パフォーマンスに影響を与える要因には、以下が含まれますが、これに限定されません。
- KotlinデーモンおよびGradleデーモンの状態。
- ディスクの速度。
- CPUモデルと使用率。
- 変更によって影響を受けるモジュールとそれらのモジュールのサイズ。
- 変更がABIであるか非ABIであるか。
ビルドレポートを使用した最適化の評価
プロジェクトとシナリオにおける最適化の影響をコンピュータで推定するには、Kotlinビルドレポートを使用できます。テキストファイル形式でレポートを有効にするには、gradle.properties
ファイルに以下のプロパティを追加してください。
kotlin.build.report.output=file
正確なバックアップを有効にする前のレポートの関連部分の例を以下に示します。
Task ':kotlin-gradle-plugin:compileCommonKotlin' finished in 0.59 s
<...>
Time metrics:
Total Gradle task time: 0.59 s
Task action before worker execution: 0.24 s
Backup output: 0.22 s // この数値に注意してください
<...>
正確なバックアップを有効にした後のレポートの関連部分の例を以下に示します。
Task ':kotlin-gradle-plugin:compileCommonKotlin' finished in 0.46 s
<...>
Time metrics:
Total Gradle task time: 0.46 s
Task action before worker execution: 0.07 s
Backup output: 0.05 s // 時間が短縮されました
Run compilation in Gradle worker: 0.32 s
Clear jar cache: 0.00 s
Precise backup output: 0.00 s // 正確なバックアップに関連
Cleaning up the backup stash: 0.00 s // 正確なバックアップに関連
<...>
すべてのGradleバージョンにおけるKotlin/JVMタスクの遅延作成
Gradle 7.3+のorg.jetbrains.kotlin.gradle.jvm
プラグインを使用するプロジェクトでは、Kotlin GradleプラグインはタスクcompileKotlin
を積極的に作成・設定しなくなりました。下位のGradleバージョンでは、すべてのタスクを登録するだけで、ドライラン時にはそれらを設定しません。Gradle 7.3+を使用する場合も同じ動作が適用されるようになりました。
コンパイルタスクのdestinationDirectory
の非デフォルトロケーション
以下のいずれかの操作を行う場合は、ビルドスクリプトに追加のコードを記述して更新してください。
- Kotlin/JVM
KotlinJvmCompile
/KotlinCompile
タスクのdestinationDirectory
のロケーションをオーバーライドする。 - 非推奨のKotlin/JS/非IRバリアントを使用し、
Kotlin2JsCompile
タスクのdestinationDirectory
をオーバーライドする。
JARファイル内のsourceSets.main.outputs
にsourceSets.main.kotlin.classesDirectories
を明示的に追加する必要があります。
tasks.jar(type: Jar) {
from sourceSets.main.outputs
from sourceSets.main.kotlin.classesDirectories
}
コンパイラ引数をHTTP統計サービスに報告しないオプション
Kotlin GradleプラグインがHTTPビルドレポートにコンパイラ引数を含めるかどうかを制御できるようになりました。場合によっては、プラグインがこれらの引数を報告する必要がないかもしれません。プロジェクトに多くのモジュールが含まれている場合、レポート内のコンパイラ引数は非常に重く、あまり役に立たないことがあります。現在、これを無効にしてメモリを節約する方法があります。gradle.properties
またはlocal.properties
で、kotlin.build.report.include_compiler_arguments=(true|false)
プロパティを使用してください。
この機能に関するフィードバックは、YouTrackまでお寄せください。
標準ライブラリ
Kotlin 1.8.20では、Kotlin/Native開発に特に役立つものを含め、さまざまな新機能が追加されました。
AutoCloseable
インターフェースのサポート- Base64エンコードとデコードのサポート
- Kotlin/Nativeでの
@Volatile
のサポート - Kotlin/Nativeで正規表現使用時のスタックオーバーフローのバグ修正
AutoCloseable
インターフェースのサポート
DANGER
新しいAutoCloseable
インターフェースは実験的であり、使用するには@OptIn(ExperimentalStdlibApi::class)
またはコンパイラ引数-opt-in=kotlin.ExperimentalStdlibApi
でオプトインする必要があります。
AutoCloseable
インターフェースは共通標準ライブラリに追加され、すべてのライブラリでリソースを閉じるための共通インターフェースとして使用できるようになりました。Kotlin/JVMでは、AutoCloseable
インターフェースはjava.lang.AutoClosable
のエイリアスです。
さらに、拡張関数use()
が追加されました。これは、選択されたリソースに対して与えられたブロック関数を実行し、例外がスローされたかどうかにかかわらず、そのリソースを正しく閉じます。
共通標準ライブラリには、AutoCloseable
インターフェースを実装するpublicなクラスはありません。以下の例では、XMLWriter
インターフェースを定義し、それを実装するリソースが存在すると仮定しています。例えば、このリソースは、ファイルを開き、XMLコンテンツを書き込み、その後ファイルを閉じるクラスである可能性があります。
interface XMLWriter : AutoCloseable {
fun document(encoding: String, version: String, content: XMLWriter.() -> Unit)
fun element(name: String, content: XMLWriter.() -> Unit)
fun attribute(name: String, value: String)
fun text(value: String)
}
fun writeBooksTo(writer: XMLWriter) {
writer.use { xml ->
xml.document(encoding = "UTF-8", version = "1.0") {
element("bookstore") {
element("book") {
attribute("category", "fiction")
element("title") { text("Harry Potter and the Prisoner of Azkaban") }
element("author") { text("J. K. Rowling") }
element("year") { text("1999") }
element("price") { text("29.99") }
}
element("book") {
attribute("category", "programming")
element("title") { text("Kotlin in Action") }
element("author") { text("Dmitry Jemerov") }
element("author") { text("Svetlana Isakova") }
element("year") { text("2017") }
element("price") { text("25.19") }
}
}
}
}
}
Base64エンコーディングのサポート
DANGER
新しいエンコードおよびデコード機能は実験的であり、使用するには@OptIn(ExperimentalEncodingApi::class)
またはコンパイラ引数-opt-in=kotlin.io.encoding.ExperimentalEncodingApi
でオプトインする必要があります。
Base64エンコードとデコードのサポートを追加しました。異なるエンコードスキームを使用し、異なる動作を示す3つのクラスインスタンスを提供します。標準のBase64エンコーディングスキームにはBase64.Default
インスタンスを使用してください。
「URLおよびファイル名セーフ」エンコーディングスキームにはBase64.UrlSafe
インスタンスを使用してください。
MIMEエンコーディングスキームにはBase64.Mime
インスタンスを使用してください。Base64.Mime
インスタンスを使用する場合、すべてのエンコード関数は76文字ごとに改行コードを挿入します。デコードの場合、不正な文字はスキップされ、例外はスローされません。
TIP
Base64.Default
インスタンスはBase64
クラスのコンパニオンオブジェクトです。その結果、Base64.Default.encode()
やBase64.Default.decode()
の代わりに、Base64.encode()
やBase64.decode()
を介してその関数を呼び出すことができます。
val foBytes = "fo".map { it.code.toByte() }.toByteArray()
Base64.Default.encode(foBytes) // "Zm8="
// Alternatively:
// Base64.encode(foBytes)
val foobarBytes = "foobar".map { it.code.toByte() }.toByteArray()
Base64.UrlSafe.encode(foobarBytes) // "Zm9vYmFy"
Base64.Default.decode("Zm8=") // foBytes
// Alternatively:
// Base64.decode("Zm8=")
Base64.UrlSafe.decode("Zm9vYmFy") // foobarBytes
既存のバッファにバイトをエンコードまたはデコードしたり、提供されたAppendable
型オブジェクトにエンコード結果を追記したりする追加の関数を使用できます。
Kotlin/JVMでは、入出力ストリームを使用してBase64エンコードとデコードを実行できるように、拡張関数encodingWith()
とdecodingWith()
も追加しました。
Kotlin/Nativeでの@Volatile
のサポート
DANGER
Kotlin/Nativeにおける@Volatile
は実験的です。いつでも削除または変更される可能性があります。オプトインが必要です(詳細は下記参照)。評価目的でのみ使用してください。この機能に関するフィードバックはYouTrackまでお寄せください。
var
プロパティに@Volatile
をアノテーションすると、バッキングフィールドがマークされ、そのフィールドへのすべての読み取りと書き込みがアトミックになり、書き込みは常に他のスレッドから見えるようになります。
1.8.20以前は、kotlin.jvm.Volatile
アノテーションが共通標準ライブラリで利用可能でした。しかし、このアノテーションはJVMでのみ有効です。Kotlin/Nativeで使用すると無視され、エラーにつながる可能性があります。
1.8.20では、JVMとKotlin/Nativeの両方で使用できる共通アノテーションkotlin.concurrent.Volatile
を導入しました。
有効にする方法
この機能を試すには、@OptIn(ExperimentalStdlibApi)
でオプトインし、-language-version 1.9
コンパイラオプションを有効にしてください。Gradleプロジェクトでは、build.gradle(.kts)
ファイルに以下を追加することで行えます。
tasks
.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask<*>>()
.configureEach {
compilerOptions
.languageVersion
.set(
org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
)
}
tasks
.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask.class)
.configureEach {
compilerOptions.languageVersion =
org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
Kotlin/Nativeで正規表現使用時のスタックオーバーフローのバグ修正
Kotlinの以前のバージョンでは、正規表現パターンが非常に単純であっても、正規表現入力に多数の文字が含まれている場合にクラッシュが発生する可能性がありました。1.8.20では、この問題が解決されました。詳細については、KT-46211を参照してください。
シリアライゼーションの更新
Kotlin 1.8.20には、Kotlin K2コンパイラのAlphaサポートと、コンパニオンオブジェクトを介したシリアライザのカスタマイズの禁止が含まれています。
Kotlin K2コンパイラ用プロトタイプシリアライゼーションコンパイラプラグイン
DANGER
K2用シリアライゼーションコンパイラプラグインのサポートはAlpha版です。使用するには、Kotlin K2コンパイラを有効にしてください。
1.8.20から、シリアライゼーションコンパイラプラグインはKotlin K2コンパイラで動作します。ぜひお試しいただき、フィードバックをお寄せください!
コンパニオンオブジェクトによる暗黙的なシリアライザカスタマイズの禁止
現在、@Serializable
アノテーションでクラスをシリアライズ可能として宣言し、同時にコンパニオンオブジェクトに@Serializer
アノテーションでカスタムシリアライザを宣言することが可能です。
例:
import kotlinx.serialization.*
@Serializable
class Foo(val a: Int) {
@Serializer(Foo::class)
companion object {
// Custom implementation of KSerializer<Foo>
}
}
この場合、@Serializable
アノテーションからはどのシリアライザが使用されているかが不明確です。実際には、クラスFoo
にはカスタムシリアライザがあります。
このような混乱を防ぐため、Kotlin 1.8.20では、このシナリオが検出された場合にコンパイラ警告を導入しました。この警告には、この問題を解決するための移行パスも含まれています。
コードでこのような構造を使用している場合は、以下のように更新することをお勧めします。
import kotlinx.serialization.*
@Serializable(Foo.Companion::class)
class Foo(val a: Int) {
// Doesn't matter if you use @Serializer(Foo::class) or not
companion object: KSerializer<Foo> {
// Custom implementation of KSerializer<Foo>
}
}
このアプローチでは、Foo
クラスがコンパニオンオブジェクトで宣言されたカスタムシリアライザを使用していることが明確です。詳細については、YouTrackチケットを参照してください。
TIP
Kotlin 2.0では、このコンパイル警告をコンパイラエラーに昇格させる予定です。この警告が表示された場合は、コードを移行することをお勧めします。
ドキュメントの更新
Kotlinのドキュメントにはいくつかの注目すべき変更が加えられました。
- Spring BootとKotlinで始める – データベースを備えたシンプルなアプリケーションを作成し、Spring BootとKotlinの機能について詳しく学びます。
- スコープ関数 – 標準ライブラリの便利なスコープ関数でコードを簡素化する方法を学びます。
- CocoaPods統合 – CocoaPodsを扱うための環境をセットアップします。
Kotlin 1.8.20をインストールする
IDEのバージョンを確認する
IntelliJ IDEA 2022.2および2022.3は、Kotlinプラグインをバージョン1.8.20に更新するよう自動的に提案します。IntelliJ IDEA 2023.1には、Kotlinプラグイン1.8.20が組み込まれています。
Android Studio Flamingo (222)およびGiraffe (223)は、次期リリースでKotlin 1.8.20をサポートします。
新しいコマンドラインコンパイラは、GitHubリリースページからダウンロードできます。
Gradle設定を構成する
Kotlinのアーティファクトと依存関係を適切にダウンロードするには、settings.gradle(.kts)
ファイルを更新してMaven Centralリポジトリを使用してください。
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
}
}
リポジトリが指定されていない場合、Gradleは非推奨のJCenterリポジトリを使用するため、Kotlinアーティファクトで問題が発生する可能性があります。