Skip to content

Kotlin 1.4.30 の新機能

リリース日: 2021年2月3日

Kotlin 1.4.30 では、新しい言語機能のプレビュー版が提供され、Kotlin/JVM コンパイラの新しい IR バックエンドが Beta に昇格したほか、さまざまなパフォーマンスと機能の改善が行われています。

新機能については、こちらのブログ投稿でもご確認いただけます。

Kotlin のリリースサイクルの詳細については、Kotlin のリリースプロセスを参照してください。

言語機能

Kotlin 1.5.0 では、JVM レコード(records)のサポート、シールドインターフェース(sealed interfaces)、および安定版のインラインクラス(inline classes)という新しい言語機能が導入される予定です。 Kotlin 1.4.30 では、これらの機能と改善をプレビューモードで試すことができます。1.5.0 のリリース前に対処できるよう、対応する YouTrack チケットでフィードバックを共有していただければ幸いです。

これらの言語機能や改善をプレビューモードで有効にするには、特定のコンパイラオプションを追加してオプトインする必要があります。詳細は以下のセクションを参照してください。

新機能のプレビューの詳細については、こちらのブログ投稿をご覧ください。

JVM レコードのサポート

JVM レコード機能は実験的(Experimental)です。将来的に削除または変更される可能性があります。 オプトインが必要であり(詳細は以下を参照)、評価目的でのみ使用してください。YouTrack でのフィードバックをお待ちしております。

JDK 16 のリリースには、record と呼ばれる新しい Java クラス型を安定化させる計画が含まれています。Kotlin のすべての利点を提供し、Java との相互運用性を維持するために、Kotlin は実験的なレコードクラスのサポートを導入しています。

Java で宣言されたレコードクラスは、Kotlin のプロパティを持つクラスと同じように使用できます。追加の手順は必要ありません。

1.4.30 以降、データクラス@JvmRecord アノテーションを使用することで、Kotlin でレコードクラスを宣言できるようになりました。

kotlin
@JvmRecord
data class User(val name: String, val age: Int)

JVM レコードのプレビュー版を試すには、コンパイラオプション -Xjvm-enable-preview-language-version 1.5 を追加してください。

JVM レコードのサポートについては引き続き作業を進めております。この YouTrack チケット を通じてフィードバックをお寄せいただければ幸いです。

実装、制限、および構文の詳細については、KEEP を参照してください。

シールドインターフェース

シールドインターフェースは実験的(Experimental)です。将来的に削除または変更される可能性があります。 オプトインが必要であり(詳細は以下を参照)、評価目的でのみ使用してください。YouTrack でのフィードバックをお待ちしております。

Kotlin 1.4.30 では、シールドインターフェース(sealed interfaces) のプロトタイプを導入します。これらはシールドクラス(sealed classes)を補完し、より柔軟な制限付きクラス階層を構築することを可能にします。

これらは、同じモジュール外では実装できない「内部的な」インターフェースとして機能します。この事実を利用して、たとえば網羅的な when 式を記述することができます。

kotlin
sealed interface Polygon

class Rectangle(): Polygon
class Triangle(): Polygon

// when() は網羅的です。モジュールのコンパイル後に
// 他の Polygon の実装が現れることはありません
fun draw(polygon: Polygon) = when (polygon) {
    is Rectangle -> // ...
    is Triangle -> // ...
}

もう一つのユースケースとして、シールドインターフェースを使用すると、1つのクラスが2つ以上のシールドスーパークラスを継承できるようになります。

kotlin
sealed interface Fillable {
   fun fill()
}
sealed interface Polygon {
   val vertices: List<Point>
}

class Rectangle(override val vertices: List<Point>): Fillable, Polygon {
   override fun fill() { /*...*/ }
}

シールドインターフェースのプレビュー版を試すには、コンパイラオプション -language-version 1.5 を追加してください。このバージョンに切り替えると、インターフェースで sealed 修飾子を使用できるようになります。この YouTrack チケット を通じてフィードバックをお寄せいただければ幸いです。

シールドインターフェースの詳細

パッケージ全体のシールドクラス階層

パッケージ全体のシールドクラス階層は実験적(Experimental)です。将来的に削除または変更される可能性があります。 オプトインが必要であり(詳細は以下を参照)、評価目的でのみ使用してください。YouTrack でのフィードバックをお待ちしております。

シールドクラスが、より柔軟な階層を形成できるようになりました。同じコンパイル単位かつ同じパッケージ内のすべてのファイルにサブクラスを持つことができます。以前は、すべてのサブクラスが同じファイル内に記述されている必要がありました。

直接のサブクラスは、トップレベルに配置することも、他の任意の数の名前付きクラス、名前付きインターフェース、または名前付きオブジェクト内にネストすることもできます。シールドクラスのサブクラスは、適切に修飾された(qualified)名前を持つ必要があり、ローカルオブジェクトや匿名オブジェクトにすることはできません。

パッケージ全体のシールドクラス階層を試すには、コンパイラオプション -language-version 1.5 を追加してください。この YouTrack チケット を通じてフィードバックをお寄せいただければ幸いです。

パッケージ全体のシールドクラス階層の詳細

改善されたインラインクラス

インラインバリュークラス(inline value classes)は Beta です。ほぼ安定していますが、将来的に移行手順が必要になる可能性があります。変更を最小限に抑えるよう最善を尽くします。インラインクラス機能に関するフィードバックを YouTrack でお待ちしております。

Kotlin 1.4.30 では、インラインクラスBeta に昇格させ、以下の機能追加と改善を行いました。

  • インラインクラスは値ベース(value-based)であるため、value 修飾子を使用して定義できるようになりました。現在、inline 修飾子と value 修飾子は互いに同等です。将来の Kotlin バージョンでは、inline 修飾子を非推奨にする予定です。

    今後、JVM バックエンドではクラス宣言の前に @JvmInline アノテーションが必要になります。

    kotlin
    inline class Name(private val s: String)
    
    value class Name(private val s: String)
    
    // JVM バックエンドの場合
    @JvmInline
    value class Name(private val s: String)
  • インラインクラスに init ブロックを持たせることができるようになりました。クラスがインスタンス化された直後に実行されるコードを追加できます。

    kotlin
    @JvmInline
    value class Negative(val x: Int) {
      init {
          require(x < 0) { }
      }
    }
  • Java コードからのインラインクラスを使用した関数の呼び出し:Kotlin 1.4.30 より前は、マングリング(名前の難読化)のために、インラインクラスを受け取る関数を Java から呼び出すことができませんでした。 今後は、手動でマングリングを無効にすることができます。このような関数を Java コードから呼び出すには、関数宣言の前に @JvmName アノテーションを追加する必要があります。

    kotlin
    inline class UInt(val x: Int)
    
    fun compute(x: Int) { }
    
    @JvmName("computeUInt")
    fun compute(x: UInt) { }
  • 本リリースでは、不適切な動作を修正するために関数のマングリングスキームを変更しました。これらの変更により ABI が変更されました。

    1.4.30 以降、Kotlin コンパイラはデフォルトで新しいマングリングスキームを使用します。コンパイラに古い 1.4.0 のマングリングスキームを強制的に使用させ、バイナリ互換性を維持するには、-Xuse-14-inline-classes-mangling-scheme コンパイラフラグを使用してください。

Kotlin 1.4.30 はインラインクラスを Beta に昇格させ、将来のリリースのいずれかで Stable にする予定です。この YouTrack チケット を通じてフィードバックをお寄せいただければ幸いです。

インラインクラスのプレビュー版を試すには、コンパイラオプション -Xinline-classes または -language-version 1.5 を追加してください。

マングリングアルゴリズムの詳細については、KEEP を参照してください。

インラインクラスの詳細

Kotlin/JVM

JVM IR コンパイラバックエンドが Beta に到達

1.4.0 で Alpha として提供された Kotlin/JVM 用の IR ベースのコンパイラバックエンドが Beta に到達しました。これは、IR バックエンドが Kotlin/JVM コンパイラのデフォルトになる前の、最後のプレステータスレベルです。

IR コンパイラによって生成されたバイナリの使用制限を廃止します。以前は、新しい JVM IR バックエンドでコンパイルされたコードは、新しいバックエンドを有効にしている場合にのみ使用できました。1.4.30 以降、そのような制限はなくなるため、新しいバックエンドを使用してライブラリなどのサードパーティ向けのコンポーネントを構築できます。新しいバックエンドの Beta 版を試し、弊社の課題トラッカーでフィードバックを共有してください。

新しい JVM IR バックエンドを有効にするには、プロジェクトの構成ファイルに以下の行を追加してください。

  • Gradle の場合:

    kotlin
    tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile::class) {
      kotlinOptions.useIR = true
    }
    groovy
    tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile) {
      kotlinOptions.useIR = true
    }
  • Maven の場合:

    xml
    <configuration>
        <args>
            <arg>-Xuse-ir</arg>
        </args>
    </configuration>

JVM IR バックエンドがもたらす変更の詳細については、こちらのブログ投稿をご覧ください。

Kotlin/Native

パフォーマンスの改善

Kotlin/Native では 1.4.30 でさまざまなパフォーマンスの改善が行われ、コンパイル時間が短縮されました。 たとえば、Networking and data storage with Kotlin Multiplatform Mobile サンプルでのフレームワークの再ビルドに必要な時間は、9.5秒(1.4.10)から4.5秒(1.4.30)に短縮されました。

Apple watchOS 64ビットシミュレータターゲット

x86 シミュレータターゲットは、バージョン 7.0 以降の watchOS で非推奨になりました。最新の watchOS バージョンに対応するため、Kotlin/Native には 64ビットアーキテクチャでシミュレータを実行するための新しいターゲット watchosX64 が追加されました。

Xcode 12.2 ライブラリのサポート

Xcode 12.2 で提供される新しいライブラリのサポートを追加しました。Kotlin コードからこれらを使用できるようになります。

Kotlin/JS

トップレベルプロパティの遅延初期化

トップレベルプロパティの遅延初期化(Lazy initialization)は実験的(Experimental)です。将来的に削除または変更される可能性があります。 オプトインが必要であり(詳細は以下を参照)、評価目的でのみ使用してください。YouTrack でのフィードバックをお待ちしております。

Kotlin/JS 用の IR バックエンドに、トップレベルプロパティの遅延初期化のプロトタイプ実装が導入されました。これにより、アプリケーションの起動時にすべてのトップレベルプロパティを初期化する必要性が減り、アプリケーションの起動時間が大幅に向上するはずです。

遅延初期化については引き続き改善を進めてまいります。現在のプロトタイプを試して、その感想や結果をこの YouTrack チケット または公式 Kotlin Slack(招待はこちら)の #javascript チャンネルで共有してください。

遅延初期化を使用するには、JS IR コンパイラでコードをコンパイルする際に -Xir-property-lazy-initialization コンパイラオプションを追加してください。

Gradle プロジェクトの改善

Gradle 構成キャッシュ(Configuration cache)のサポート

1.4.30 以降、Kotlin Gradle プラグインは 構成キャッシュ 機能をサポートします。これによりビルドプロセスが高速化されます。コマンドを実行すると、Gradle は構成フェーズを実行してタスクグラフを計算します。Gradle はその結果をキャッシュし、その後のビルドで再利用します。

この機能の使用を開始するには、Gradle コマンドを使用するか、IntelliJ ベースの IDE をセットアップしてください。

標準ライブラリ

テキストの大文字・小文字変換用のロケールに依存しない API

ロケールに依存しない(locale-agnostic)API 機能は実験的(Experimental)です。将来的に削除または変更される可能性があります。 評価目的でのみ使用してください。 YouTrack でのフィードバックをお待ちしております。

本リリースでは、文字列や文字の大文字・小文字を変更するための、ロケールに依存しない実験的な API を導入します。 現在の toLowerCase()toUpperCase()capitalize()decapitalize() API 関数はロケールに依存しています。つまり、異なるプラットフォームのロケール設定がコードの動作に影響を与える可能性があります。たとえば、トルコ語のロケールでは、文字列 "kotlin" を toUpperCase を使用して変換すると、結果は "KOTLIN" ではなく "KOTLİN" になります。

kotlin
// 現在の API
println("Needs to be capitalized".toUpperCase()) // NEEDS TO BE CAPITALIZED

// 新しい API
println("Needs to be capitalized".uppercase()) // NEEDS TO BE CAPITALIZED

Kotlin 1.4.30 は以下の代替手段を提供します。

  • String 関数用:

    以前のバージョン1.4.30 の代替手段
    String.toUpperCase()String.uppercase()
    String.toLowerCase()String.lowercase()
    String.capitalize()String.replaceFirstChar { it.uppercase() }
    String.decapitalize()String.replaceFirstChar { it.lowercase() }
  • Char 関数用:

    以前のバージョン1.4.30 の代替手段
    Char.toUpperCase()Char.uppercaseChar(): Char
    Char.uppercase(): String
    Char.toLowerCase()Char.lowercaseChar(): Char
    Char.lowercase(): String
    Char.toTitleCase()Char.titlecaseChar(): Char
    Char.titlecase(): String

Kotlin/JVM の場合、明示的な Locale パラメータを持つオーバーロードされた uppercase()lowercase()、および titlecase() 関数もあります。

テキスト処理関数の変更内容の完全なリストについては、KEEP を参照してください。

明確な Char-to-code および Char-to-digit 変換

Char 変換用の明確な API 機能は実験的(Experimental)です。将来的に削除または変更される可能性があります。 評価目的でのみ使用してください。 YouTrack でのフィードバックをお待ちしております。

現在の Char から数値への変換関数(異なる数値型で表現された UTF-16 コードを返す)は、文字列の数値を返す同様の String-to-Int 変換と混同されることがよくあります。

kotlin
"4".toInt() // 4 を返す
'4'.toInt() // 52 を返す
// また、Char '4' に対して数値 4 を返す共通の関数はありませんでした

この混乱を避けるために、Char 変換を以下の2つの明確な名前の関数セットに分けることにしました。

  • Char の整数コードを取得する関数、および指定されたコードから Char を構築する関数:

    kotlin
    fun Char(code: Int): Char
    fun Char(code: UShort): Char
    val Char.code: Int
  • Char をそれが表す数字の数値に変換する関数:

    kotlin
    fun Char.digitToInt(radix: Int): Int
    fun Char.digitToIntOrNull(radix: Int): Int?
  • 非負の1桁の数字を表す Int を、対応する Char 表現に変換するための拡張関数:

    kotlin
    fun Int.digitToChar(radix: Int): Char

詳細は KEEP を参照してください。

Serialization の更新

Kotlin 1.4.30 と共に、いくつかの新機能を含む kotlinx.serialization 1.1.0-RC をリリースします。

  • インラインクラスのシリアル化サポート
  • 符号なしプリミティブ型のシリアル化サポート

インラインクラスのシリアル化サポート

Kotlin 1.4.30 以降、インラインクラスをシリアル化可能(serializable)にできるようになりました。

kotlin
@Serializable
inline class Color(val rgb: Int)

この機能には、新しい 1.4.30 IR コンパイラが必要です。

シリアル化フレームワークは、シリアル化可能なインラインクラスが他のシリアル化可能なクラスで使用される場合、それらをボックス化しません。

詳細は kotlinx.serializationドキュメントをご覧ください。

符号なしプリミティブ型のシリアル化サポート

1.4.30 からは、符号なしプリミティブ型(UIntULongUByteUShort)に対して kotlinx.serialization の標準 JSON シリアライザーを使用できます。

kotlin
@Serializable
class Counter(val counted: UByte, val description: String)
fun main() {
   val counted = 239.toUByte()
   println(Json.encodeToString(Counter(counted, "tries")))
}

詳細は kotlinx.serializationドキュメントをご覧ください。