※ソース記事
※Kotlin/JS、Kotlin/Nativeについては割愛します。
リリース日:2023/4/3
Kotlin 1.8.20のリリースが公開され、こちらに最大のハイライトのいくつかがある。
- 新しいKotlin K2コンパイラの更新
- 新しい実験的Kotlin/Wasmターゲット
- Gradleでの新しいJVMの増分コンパイルがデフォルト化
- Kotlin/Nativeターゲットの更新
- Kotlin MultiplatformにおけるGradle複合ビルドのプレビュー
- XcodeにおけるGradleエラー出力の改善
- 標準ライブラリにおけるAutoCloseableインターフェイスの実験的サポート
- 標準ライブラリにおけるBase64エンコーディングの実験的サポート
こちらの映像で、変更点の短い概要をみつけることができる。
IDEのサポート
1.8.20をサポートするKotlinプラグインは以下。
IDE | サポートバージョン |
---|---|
IntelliJ IDEA | 2022.2.x, 2022.3.x, 2023.1.x |
Android Studio | Flamingo (222) |
Kotlin成果物と依存関係を適切にダウンロードするためには、Maven Centralリポジトリを使うためにGradle設定を行うこと
新しいKotlin K2コンパイラの変更点
KotlinチームはK2コンパイラの安定化を継続している。Kotlin 1.7.0のアナウンスで述べたように、まだAlphaである。このリリースではK2 Betaへの道におけるさらなる改善が導入されている。
この1.8.20リリースからKotlin K2コンパイラでは、以下が行われている。
- serializationプラグインのプレビュー版
- JS IRコンパイラのAlphaサポートの提供
-
新しい言語バージョンであるKotlin 2.0の将来のリリースの紹介
新しいコンパイラとその利点について、次の映像で知識を深める。 - 皆さんが新しいKotlin K2コンパイラについて知らなければならないこと
- 新しいKotlin K2コンパイラ エキスパートレビュー
Kotlin K2コンパイラの有効化方法
Kotlin K2コンパイラを有効化し、テストするためには、次のコンパイラオプションで新しい言語バージョンを使う。
-language-version 2.0
build.gradle(.kts)
ファイルで、指定することができる。
kotlin {
sourceSets.all {
languageSettings {
languageVersion = "2.0"
}
}
}
以前の-Xuse-k2
コンパイラオプションは非推奨になった。
新しいKotlin K2コンパイラのAlphaバージョンは、JVMとJS IRプロジェクトでのみ動作する。Kotlin/Nativeやマルチプラットフォームプロジェクトはサポートされていない。
新しいK2コンパイラにおけるフィードバック
是非ご意見をお聞かせください!
- Kotlin Slackで直接K2開発者へフィードバックを提供 - 招待を受け、#k2-early-adoptersチャンネルに参加
- 我々のissue trackerで、新しいK2コンパイラで直面した問題を報告
- 利用統計の送信オプションを有効化し、JetBrainsにK2利用についての匿名データの収集を許可する。
言語
Kotlinが進化し続けるように、我々は1.8.20で新しい言語機能のためのプレビューバージョンを導入している。
- Enumクラス値関数のモダンで高性能な代替
- dataクラスと調和するためのdataオブジェクトのプレビュー
- インラインクラスでの本体を持つセカンダリコンストラクタの制限の撤廃
Enumクラス値関数のモダンで高性能な代替
この機能は実験的である。いつでも削除あるいは変更される可能性がある。オプトインが必要(以下参照)である。評価目的のためにのみ使用すること。YouTrack上でご意見をお聞かせください。
Enumクラスは合成values()
関数を持ち、定義されたenum定数の配列を返却する。しかし、配列を使うことはKotlinとJavaでに隠れた性能問題を引き起こすことがある。さらにほとんどのAPIはコレクションを使い、最終的に変換が必要である。これらの問題を修正するため、Enumクラスのためのentries
プロパティを導入し、values()
関数の代わりに使うべきとした。呼び出し時に、entries
プロパティは、事前割り当てされた定義されたenum定数の変更できないリストを返却する。
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
)
}
IntelliJ IDEA 2023.1から、この機能に対してオプトインした場合、適切にIDEがvalues()
からentries
への変換を通知し、クイックフィックスを提示する。
この提案の詳細は、KEEP noteを参照のこと。
data classと調和するためのdata objectのプレビュー
data objectはシングルトンの意味と簡潔なtoString()
表現を持つobjectを宣言することが可能になる。このスニペットでは、object宣言にdata
キーワードを追加することで、toString()
出力の可読性を向上することがわかる。
package org.example
object MyObject
data object MyDataObject
fun main() {
println(MyObject) // org.example.MyObject@1f32e575
println(MyDataObject) // MyDataObject
}
特に(sealedクラス
やsealedインターフェイス
階層のような)sealed
階層には、data object
はdata class
宣言と便利に並んで使うことができるため、ぴったりフィットする。このスニペットでは、プレーンなobject
の代わりにdataオブジェクト
として、EndOfFile
を宣言することで、手動でオーバーライドする必要なく、美しいtoString
を得ることができる。これは付属のdata class宣言との調和を維持する。
sealed interface ReadResult
data class Number(val number: Int) : ReadResult
data class Text(val text: String) : ReadResult
data object EndOfFile : ReadResult
fun main() {
println(Number(7)) // Number(number=7)
println(EndOfFile) // EndOfFile
}
data objectの意味合い
Kotlin 1.7.20での最初のプレビューバージョンから、data objectの意味合いが改良された。今ではコンパイラによって、多くの便利な関数が生成される。
toString
data objectのtoString()
関数はオブジェクトの単純な名前を返却する。
data object MyDataObject {
val x: Int = 3
}
fun main() {
println(MyDataObject) // MyDataObject
}
equalsとhashCode
data objectのequals()
関数はあるdataオブジェクト
の型を持つすべてのオブジェクトが等しいと評価されることを保証する。ほとんどの場合、実行時にあるdataオブジェクトの単一のインスタンスを持つだけであろう(要するにdataオブジェクト
はシングルトンを宣言する)。しかし、同じ型の異なるオブジェクトが実行時に生成されるエッジケース(例えば、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
// 例えライブラリがMySingletonの二つ目のインスタンスを強制的に作っても`equals`はtrueを返す:
println(MySingleton == evilTwin) // true
// ===経由でdata objectを比較しないこと。
println(MySingleton === evilTwin) // false
}
fun createInstanceViaReflection(): MySingleton {
// Kotlinのリフレクションでは、data objectのインスタンス化は許可されていない。
// ここでは新しいMySingletonのインスタンスを「力ずくで」作る。(例 Javaプラットフォームのリフレクション)
// このようなことはしないこと!
return (MySingleton.javaClass.declaredConstructors[0].apply { isAccessible = true } as Constructor<MySingleton>).newInstance()
}
生成されたhashCode()
関数のふるまいはequals()
関数のものと一致しており、そのため、あるdata object
のすべての実行時インスタンスは、同じハッシュコードを持つ。
data objectのcopyとcomponentN関数は無い
data object
とdata class
宣言は度々一緒に使用し、いくつか類似点を持つ一方で、いくつかの関数はdata object
には生成されない。
data object
宣言はシングルトンオブジェクトとして使うことを意図しているため、copy()
関数は生成されない。シングルトンパターンはクラスのインスタンス化を単一のインスタンスに制限するので、インスタンスのコピー作成を許可することは、その制限に違反するだろう。
また、data class
と異なり、data object
はdataプロパティを一つも持たない。そのようなオブジェクトを分解しようとすることは意味がないため、componentN()
関数は生成されない。
YouTrackでこの機能についてのご意見をお聞かせください。
data objectプレビューの有効化方法
この機能を試すには、-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
)
}
インラインクラスでの本体を持つセカンダリコンストラクタの制限の撤廃
この機能は実験的である。いつでも削除あるいは変更される可能性がある。オプトインが必要(以下参照)である。評価目的のためにのみ使用すること。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
)
}
この機能を試し、YouTrackですべての報告を提出することをお勧めする。そうすればKotlin1.9.0でデフォルトにすることができる。
Kotlinのinclineクラスの開発について詳しくはこのKEEPをご覧ください。
新しいKotlin/WASMターゲット
Kotlin/Wasm (Kotlin WebAssembly)はこのプレビューリリースで実験的になっている。KotlinチームはWebAssemblyが将来性のある技術であることを見出し、それを使い、Kotlinのすべての利点を得るためのより良い方法を見つけたいと思っている。
WebAssemblyバイナリフォーマットは自身のVMで動作するため、プラットフォーム独立である。ほぼすべてのブラウザはWebAssemblly 1.0をすでにサポートしている。WebAssembllyを実行するための環境をセットアップするには、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-RC2のプレビューリリースから、実験的なプロジェクトでえ、Kotlin/WASMを使うことができる。Kotlin/WASM用のKotlin標準ライブラリ(stdlib
)とテストライブラリ(kotlin.test
)が設定なしで提供されている。IDEのサポートは将来のリリースで追加されるだろう。
Kotlin/WASMについて詳しくはこのYouTube映像でご覧ください。
Kotlin/WASMの有効化方法
Kotlin/WASMを有効化し試すには、build.gradle.kts
ファイルを更新すること。
plugins {
kotlin("multiplatform") version "1.8.20-RC2"
}
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
}
}
Kotlin/WASMのサンプルGitHubリポジトリをチェックしてください。
Kotlin/WASMプロジェクトを実行するには、対象の環境設定を更新する必要がある。
Chrome
- バージョン109用
--js-flags=--experimental-wasm-gc
コマンドライン引数でアプリケーションを実行する。 - バージョン110以上用
- ブラウザで、
chrome://flags/#enable-webassembly-garbage-collection
に遷移する - WebAssembly Garbage Collectionを有効にする
- ブラウザを再起動する
- ブラウザで、
Firefox
- バージョン109以上用
- ブラウザで、
about:config
に遷移する -
javascript.options.wasm_function_references
とjavascript.options.wasm_gc
を有効にする - ブラウザを再起動する
- ブラウザで、
Edge
- バージョン109以上用
--js-flags=--experimental-wasm-gc
コマンドライン引数でアプリケーションを実行する。
Kotlin/WASMにおけるフィードバック
是非ご意見をお聞かせください!
- Kotlin Slackで直接開発者へフィードバックを提供 - 招待を受け、#webassemblyチャンネルに参加
- 我々のissue trackerで、Kotlin/WASMで直面した問題を報告
Kotlin/JVM
Kotlin 1.8.20では、Javaの合成プロパティ参照のプレビューと、kaptスタブ生成タスクのJVM IRバックエンドのデフォルトサポートが導入されている。
Javaの合成プロパティ参照のプレビュー
この機能は実験的である。いつでも削除あるいは変更される可能性がある。評価目的のためにのみ使用すること。YouTrack上でご意見をお聞かせください。
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では常にperson.age
を書くことが許可されてきた。そこでは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
)
}
kaptスタブ生成タスクのJVM IRバックエンドのデフォルトサポート
Kotlin 1.7.20で、kaptスタブ生成タスクのJVM IRバックエンドのサポートが導入された。今回のリリースから、このサポートはデフォルトで動作する。もはやそれを有効化するために、gradle.properties
でkapt.use.jvm.ir=true
を指定する必要は無い。この機能についてYouTrack上でご意見をお聞かせください。
Gradle
Kotlin 1.8.20はいくつかのMultiplatformプラグインでの特別なケースを除いてGradle 6.8から7.6までと完全に互換性がある。最新のGradleリリースまでGradleバージョンを上げて使うこともできるが、その場合、非推奨警告に直面するか、いくつかの新しいGradle機能が動作しない可能性があることに注意すること。
このバージョンでは以下の変更がもたらされている。
- Gradleプラグインのバージョンの新しい統一
- Gradleでの新しいJVM差分コンパイルのデフォルト化
- コンパイルタスクの出力の正確なバックアップ
- 全Gradleバージョン用の遅延Kotlin/JVMタスク生成
- コンパイルタスクの宛先ディレクトリのデフォルト以外の場所
- HTTP統計サービスへコンパイル引数を報告回避する機能
Gradleプラグインのバージョンの新しい統一
Gradleは共に動作しなければならない依存性が常にバージョンが統一されていることを保証する方法を提供している。Kotlin 1.8.20でもこのアプローチを採用した。それはデフォルトで動作し、有効にするために構成を変更したり、更新する必要はない。さらにKotlin Gradleプラグインの推移的依存性を解決するための回避策に頼る必要はもう無い。
この機能についてYouTrackでご意見をお聞かせください。
Gradleでの新しいJVM差分コンパイルのデフォルト化
差分コンパイルの新しアプローチは、Kotlin 1.7.0から利用可能であったが、現在ではデフォルトで動作する。有効にするためにgradle.properties
にkotlin.incremental.useClasspathSnapshot=true
を指定する必要はもう無い。
このことについてご意見をお聞かせください。YouTrackで問題を報告することができる。
コンパイルタスクの出力の正確なバックアップ
コンパイルタスクの出力の正確なバックアップは実験的である。使うには、gradle.properties
にkotlin.compiler.preciseCompilationResultsBackup=true
を追加すること。YouTrackでご意見をお聞かせください。
Kotlin 1.8.20から、正確なバックアップを有効にすることができ、それによって、Kotlinが差分コンパイルでリコンパイルするクラス群のみが、バックアップされるようになる。フルおよび正確なバックアップにより、コンパイルエラーの後で再度差分的にビルドを実行することができる。正確なバックアップは、フルバックアップに比べてビルド時間も節約する。フルバックアップは巨大なプロジェクト、あるいは多くのタスクがバックアップを行っている場合、あるいはプロジェクトが遅いHDDに配置されている場合特に、著しく時間がかかるかもしれない。
この最適化は実験的である。gradle.properties
ファイルにkotlin.compiler.preciseCompilationResultsBackup
Gradleプロパティを追加することで有効にすることができる。
kotlin.compiler.preciseCompilationResultsBackup=true
※こちらに、JetBrainsでの正確なバックアップの例と、ビルドレポートを使った最適化の評価が記載されています。
全Gradleバージョン用の遅延Kotlin/JVMタスク生成
Gradle 7.3以上の"org.jetbrains.kotlin.gradle.jvm"プラグインを使ったプロジェクト用に、Kotlin Gradleプラグインは"compileKotlin"タスクを積極的に作り、設定することはもう無い。より古いGradleバージョンでは、すべてのタスクを単に登録し、リハーサルで設定を行わない。現在、同じ振る舞いがGradle 7.3以上を使うときに導入されている。
コンパイルタスクの宛先ディレクトリのデフォルト以外の場所
次のうちの一つをする場合、いくつかの追加コードでビルドスクリプトを更新すること。
- Kotlin/JVMの
KotlinJvmCompile
/KotlinCompile
タスクのdestinationDirectory
の場所を上書きすること - 非推奨のKotlin/JS/Non-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インターフェイスのサポート
新しいAutoCloseableインターフェイスは実験的であり、使うに@OptIn(ExperimentalStdlibApi::class)
か、-opt-in=kotlin.ExperimentalStdlibApi
コンパイラ引数でオプトインが必要である。
AutoCloseable
インターフェイスは、共通の標準ライブラリに追加されたので、リソースを閉じるためにすべてのライブラリ用に一つの共通インターフェイスを使うことができる。Kotlin/JVMではAutoCloseable
インターフェイスはjava.lang.AutoCoseable
のエイリアスである。
さらに拡張関数use()
が現在は含まれており、それは例外が発生しようがしまいが、選択されたリソース上で与えられたブロック関数を実行した後で正しくリソースをクローズする。
標準の共通ライブラリに、AutoCloseable
インターフェイスを実装する公開クラスは存在しない。以下の例では、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エンコーディングのサポート
Base64エンコーディングとデコーディングのサポートが追加された。3つのclassインスタンスが提供されており、それぞれ異なるエンコーディングスキームを使い、異なる振る舞いを示す。標準のBase64エンコーディングスキーム用に、Base64.Default
インスタンスを使うこと。
URLとファイル名セーフなエンコーディングスキーム用に、Base64.UrlSafe
インスタンスを使うこと。
MIMEエンコーディングスキーム用には、Base64.Mime
インスタンスを使うこと。Base64.Mime
インスタンスを使う場合、すべてのエンコーディング関数は、76文字で改行を挿入する。デコーディングの場合、不正な文字はスキップし、例外をスローしない。
Base64.Default
インスタンスはBase64
クラスのcompanion objectである。結果として、Base64.Default.encode()
とBase64.Default.decode()
の代わりに、Base64.encode()
とBase64.decode()
経由でその関数を呼び出すことができる。
val foBytes = "fo".map { it.code.toByte() }.toByteArray()
Base64.Default.encode(foBytes) // "Zm8="
// あるいは:
// Base64.encode(foBytes)
val foobarBytes = "foobar".map { it.code.toByte() }.toByteArray()
Base64.UrlSafe.encode(foobarBytes) // "Zm9vYmFy"
Base64.Default.decode("Zm8=") // foBytes
// あるいは:
// Base64.decode(foBytes)
Base64.UrlSafe.decode("Zm9vYmFy") // foobarBytes
エンコード結果に、提供されたAppendable
型オブジェクトを追加するのと同様に、既存のバッファにbyteをエンコードあるいはデコードするために、追加の関数を使うことができる。
Kotlin/JVMでは、入力と出力ストリームでBase64エンコーディングとデコーディングを実行できるように、encodingWith()
とdecodingWith()
拡張関数も追加されている。
Kotlin/Nativeでの@Volatileのサポート
var
プロパティを@Volatile
でアノテートする場合、このフィールドへのどんな読み書きもアトミックであり、書き込みは常に他のスレッドから参照可能であることを、バッキングフィールドがマークされる。
1.8.20より前は、kotlin.jvm.Volatile
アノテーションが、共通の標準ライブラリで利用可能なだけだった。しかし、このアノテーションはJVMでのみ有効である。Kotlin/Nativeで使う場合、無視され、エラーをもたらすことがありうる。
1.8.20では、共通のアノテーションkotlin.concurrent.Volatile
が導入され、JVMとKotlin/Native両方で使うことができる。
有効化方法
この機能を試すには、@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
)
}
Kotlin/Nativeの正規表現の使用時のスタックオーバーフローに対するバグフィックス
Kotlinの以前のバージョンで、正規表現パターンが非常に単純でも、正規表現の入力が大量の文字を含む場合、クラッシュが起こることがあった。1.8.20ではこの問題は解決された。詳しくはKT-46211を参照のこと。
Serializationの更新
Kotlin 1.8.20ではKotlin K2コンパイラのAlphaサポートと、companion object経由でのシリアライザのカスタマイズの禁止がもたらされている。
Kotlin K2コンパイラのためのプロトタイプのシリアライゼーションコンパイラプラグイン
K2用のシリアライゼーションコンパイラプラグインのサポートはAlphaである。使うには[Kotlin K2コンパイラを有効にすること]。(https://kotlinlang.org/docs/whatsnew1820.html#how-to-enable-the-kotlin-k2-compiler)
1.8.20から、シリアライゼーションコンパイラプラグインはKotlin K2コンパイラと動作する。試して、ご意見をお聞かせください。
companion object経由での暗黙のシリアライザーのカスタマイズの禁止
現在、クラスを@Serializable
でシリアライズ可能に宣言することができ、同時にそのcompanion object上で、@Serializerアノテーションをつけることでカスタムシリアライザーを宣言することができる。
例:
import kotlinx.serialization.*
@Serializable
class Foo(val a: Int) {
@Serializer(Foo::class)
companion object {
// KSerializer<Foo>のカスタマイズ実装
}
}
この場合、@Serializable
アノテーションから、どのシリアライザーが使われるのか、明確でない。実際は、Foo
クラスはカスタムシリアライザーを持っている。
この種の混乱を避けるため、Kotlin 1.8.20では、このシナリオが検出されるとコンパイラ警告が導入された。その警告は、この問題を解決するために可能な移行パスを含んでいる。
コードでそのような構成物を使う場合、次のように更新することを推奨している。
import kotlinx.serialization.*
@Serializable(Foo.Companion::class)
class Foo(val a: Int) {
// @Serializer(Foo::class)を使うかどうかということは関係ない
companion object: KSerializer<Foo> {
// KSerializer<Foo>のカスタマイズ実装
}
}
このアプローチでは、Fooクラスがcompanionオブジェクトでカスタムシリアライザーを使うことが明確である。詳しくはYouTrackチケットを参照のこと。
ドキュメントの更新
Kotlinドキュメンテーションでは、いくつかの注目に値する変更がある。
- SpringBootとKotlin入門 - データベースを使う簡単なアプリケーションを作り、SpringBootとKotlinの機能について知識を深める
- スコープ関数 - 標準ライブラリから有益なスコープ関数を使い、コードをシンプルにする方法を学ぶ
- Cocoa pod統合 - CocoaPodと連携する環境をセットアップする
Kotlin 1.8.20のインストール
IDEバージョンのチェック
IntelliJ IDEA2022.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成果物と依存性を正しくダウンロードするため、settting.gradle.kts
ファイルを更新し、Maven Centralリポジトリを使うこと。
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
}
}
リポジトリが指定されていない場合、Gradleは衰退しつつあるJCenterリポジトリを使い、Kotlin成果物で問題を引き落とすことがありうる。