メインコンテンツまでスキップ

Kotlin 1.4.30の新機能

Released: 3 February 2021

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

こちらのブログ記事で、新機能について学ぶこともできます。

言語機能

Kotlin 1.5.0 では、新しい言語機能、つまり JVM records のサポート、sealed interfaces、および Stable inline classes が提供される予定です。 Kotlin 1.4.30 では、これらの機能と改善点をプレビューモードで試すことができます。 対応する YouTrack チケットでフィードバックをお寄せいただけると幸いです。1.5.0 のリリース前に対応することができます。

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

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

JVM records のサポート

注記

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

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

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

1.4.30 以降では、データクラス@JvmRecord アノテーションを使用して、Kotlin で record クラスを宣言できます。

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

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

JVM records のサポートを引き続き改善していきます。この YouTrack チケット を使用してフィードバックをお寄せいただけると幸いです。

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

Sealed interfaces

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

Kotlin 1.4.30 では、sealed interfaces のプロトタイプを提供しています。これらは sealed classes を補完し、より柔軟な制限付きクラス階層を構築することを可能にします。

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

sealed interface Polygon

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

// when() は網羅的です。モジュールのコンパイル後、他のポリゴン実装は表示されません
fun draw(polygon: Polygon) = when (polygon) {
is Rectangle `->` // ...
is Triangle `->` // ...
}

別のユースケース: sealed interfaces を使用すると、クラスを 2 つ以上の sealed スーパークラスから継承できます。

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

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

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

sealed interfaces の詳細はこちら

Package-wide sealed class hierarchies

Package-wide hierarchies of sealed classes は Experimental です。いつでも削除または変更される可能性があります。 オプトインが必要です(以下の詳細を参照)。評価目的でのみ使用してください。 YouTrack でのフィードバックをお待ちしております。

Sealed classes は、より柔軟な階層を形成できるようになりました。同じコンパイルユニットおよび同じパッケージのすべてのファイルにサブクラスを持つことができます。以前は、すべてのサブクラスが同じファイルに存在する必要がありました。

直接のサブクラスは、トップレベルにすることも、他の名前付きクラス、名前付きインターフェース、または名前付きオブジェクトの中にネストすることもできます。sealed class のサブクラスは、適切に修飾された名前を持つ必要があり、ローカルオブジェクトでも匿名オブジェクトでもかまいません。

package-wide hierarchies of sealed classes を試すには、コンパイラオプション -language-version 1.5 を追加します。この YouTrack チケット を使用してフィードバックをお寄せいただけると幸いです。

package-wide hierarchies of sealed classes の詳細はこちら

Inline classes の改善

Inline value classes は Beta にあります。ほぼ安定していますが、将来的には移行手順が必要になる場合があります。変更を最小限に抑えるように最善を尽くします。inline classes 機能に関するフィードバックを YouTrack にお寄せいただけると幸いです。

Kotlin 1.4.30 では、inline classesBeta に昇格し、次の機能と改善がもたらされます。

  • inline classes は value-based であるため、value 修飾子を使用して定義できます。inline 修飾子と value 修飾子は、現在互いに同等です。 将来の Kotlin バージョンでは、inline 修飾子を非推奨にする予定です。

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

    inline class Name(private val s: String)

    value class Name(private val s: String)

    // For JVM backends
    @JvmInline
    value class Name(private val s: String)
  • Inline classes には init ブロックを含めることができます。クラスがインスタンス化された直後に実行されるコードを追加できます。

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

    inline class UInt(val x: Int)

    fun compute(x: Int) { }

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

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

Kotlin 1.4.30 では、inline classes がベータ版に昇格し、今後のリリースで安定版にする予定です。この YouTrack チケット を使用してフィードバックをお寄せいただけると幸いです。

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

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

inline classes の詳細はこちら

Kotlin/JVM

JVM IR コンパイラバックエンドがベータ版に到達

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

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

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

  • Gradle の場合:

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

    <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 of top-level properties は Experimental です。いつでも削除または変更される可能性があります。 オプトインが必要です(以下の詳細を参照)。評価目的でのみ使用してください。 YouTrack でのフィードバックをお待ちしております。

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

遅延初期化の改善を続けていきます。現在のプロトタイプを試して、ご意見や結果を この YouTrack チケット または公式の Kotlin Slack#javascript チャンネルで共有してください(こちら で招待状を入手してください)。

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

Gradle プロジェクトの改善

Gradle 構成キャッシュのサポート

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

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

標準ライブラリ

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

The locale-agnostic API feature is Experimental。いつでも削除または変更される可能性があります。 評価目的でのみ使用してください。 YouTrack でのフィードバックをお待ちしております。

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

// current API
println("Needs to be capitalized".toUpperCase()) // NEEDS TO BE CAPITALIZED

// new 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 からコードおよび Char から数字への明確な変換

注記

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

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

"4".toInt() // returns 4
'4'.toInt() // returns 52
// and there was no common function that would return the numeric value 4 for Char '4'

この混乱を避けるために、Char 変換を、明確に名前が付けられた次の 2 つの関数セットに分離することにしました。

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

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

    fun Char.digitToInt(radix: Int): Int
    fun Char.digitToIntOrNull(radix: Int): Int?
  • 表される負でない 1 桁の数字を対応する Char に変換する Int の拡張関数 表現:

    fun Int.digitToChar(radix: Int): Char

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

シリアライゼーションの更新

Kotlin 1.4.30 とともに、kotlinx.serialization 1.1.0-RC をリリースします。これには、いくつかの新機能が含まれています。

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

インラインクラスのシリアライゼーションのサポート

Kotlin 1.4.30 以降では、インラインクラスを シリアライズ可能 にすることができます。

@Serializable
inline class Color(val rgb: Int)

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

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

詳細については、kotlinx.serialization ドキュメント を参照してください。

符号なしプリミティブ型のシリアライゼーションのサポート

1.4.30 以降では、kotlinx.serialization の標準 JSON シリアライザを 符号なしプリミティブ型: UIntULongUByte、および UShort:

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

詳細については、kotlinx.serialization ドキュメント を参照してください。