Kotlin 1.5.20 の新機能
Kotlin 1.5.20では、1.5.0の新機能で発見された問題の修正が行われ、さまざまなツール改善も含まれています。
変更点の概要は、リリースブログ記事と以下の動画で確認できます。
Kotlin/JVM
Kotlin 1.5.20では、JVMプラットフォームで以下のアップデートが行われました。
- invokedynamicによる文字列連結
- JSpecifyのnull可能性アノテーションのサポート
- KotlinとJavaのコードを持つモジュール内でのJavaのLombokによって生成されたメソッド呼び出しのサポート
invokedynamicによる文字列連結
Kotlin 1.5.20では、文字列連結がJVM 9+ターゲット上のdynamic invocations
(invokedynamic
)にコンパイルされるようになり、最新のJavaバージョンに対応しています。
より正確には、文字列連結にはStringConcatFactory.makeConcatWithConstants()
を使用します。
以前のバージョンで使用されていたStringBuilder.append()
による連結に戻すには、コンパイラオプション-Xstring-concat=inline
を追加します。
コンパイラオプションの追加方法については、Gradle、Maven、およびコマンドラインコンパイラを参照してください。
JSpecifyのnull可能性アノテーションのサポート
Kotlinコンパイラは、さまざまな種類のnullability annotationsを読み取って、JavaからKotlinにnull可能性情報を渡すことができます。バージョン1.5.20では、JSpecify projectのサポートが導入されました。これには、Javaのnull可能性アノテーションの標準化された統一セットが含まれます。
JSpecifyを使用すると、より詳細なnull可能性情報を提供して、KotlinがJavaとのnull安全性を維持できるようにすることができます。宣言、パッケージ、またはモジュールのスコープに対してデフォルトのnull可能性を設定したり、パラメトリックなnull可能性を指定したりできます。詳細については、JSpecify user guideを参照してください。
KotlinがJSpecifyアノテーションをどのように処理できるかの例を以下に示します。
// JavaClass.java
import org.jspecify.nullness.*;
@NullMarked
public class JavaClass {
public String notNullableString() { return ""; }
public @Nullable String nullableString() { return ""; }
}
// Test.kt
fun kotlinFun() = with(JavaClass()) {
notNullableString().length // OK
nullableString().length // Warning: receiver nullability mismatch
}
1.5.20では、JSpecifyによって提供されるnull可能性情報に従ったすべてのnull可能性の不一致が警告として報告されます。
JSpecifyを使用する際にstrict mode(エラー報告あり)を有効にするには、-Xjspecify-annotations=strict
および-Xtype-enhancement-improvements-strict-mode
コンパイラオプションを使用します。
JSpecifyプロジェクトは活発に開発が進められていることに注意してください。そのAPIと実装はいつでも大幅に変更される可能性があります。
null-safetyとplatform typesの詳細はこちら。
KotlinとJavaのコードを持つモジュール内でのJavaのLombokによって生成されたメソッド呼び出しのサポート
LombokコンパイラプラグインはExperimentalです。 いつでも削除または変更される可能性があります。評価目的でのみ使用してください。 YouTrackでフィードバックをお待ちしております。
Kotlin 1.5.20では、実験的なLombok compiler pluginが導入されています。このプラグインを使用すると、KotlinとJavaのコードを持つモジュール内でJavaのLombokの宣言を生成して使用できます。LombokアノテーションはJavaソースでのみ機能し、Kotlinコードで使用すると無視されます。
このプラグインは、次のアノテーションをサポートしています。
@Getter
,@Setter
@NoArgsConstructor
,@RequiredArgsConstructor
, および@AllArgsConstructor
@Data
@With
@Value
現在もこのプラグインの開発を続けています。詳細な現状については、LombokコンパイラプラグインのREADMEをご覧ください。
現在、@Builder
アノテーションをサポートする予定はありません。ただし、YouTrackの@Builder
に投票していただければ、検討することができます。
Kotlin/Native
Kotlin/Native 1.5.20では、新機能のプレビューとツール改善が提供されます。
生成されたObjective-CヘッダーへのKDocコメントのオプトインエクスポート
生成されたObjective-CヘッダーへのKDocコメントのエクスポート機能はExperimentalです。 いつでも削除または変更される可能性があります。 オプトインが必要です(詳細は下記参照)。評価目的でのみ使用してください。 YouTrackでフィードバックをお待ちしております。
Kotlin/Nativeコンパイラを設定して、Kotlinコードからdocumentation comments (KDoc)をエクスポートできるようになりました。 それから生成されたObjective-Cフレームワークにエクスポートすると、フレームワークの利用者に表示されます。
たとえば、KDocを使用した次のKotlinコード:
/**
* Prints the sum of the arguments.
* Properly handles the case when the sum doesn't fit in 32-bit integer.
*/
fun printSum(a: Int, b: Int) = println(a.toLong() + b)
次のObjective-Cヘッダーが生成されます。
/**
* Prints the sum of the arguments.
* Properly handles the case when the sum doesn't fit in 32-bit integer.
*/
+ (void)printSumA:(int32_t)a b:(int32_t)b __attribute__((swift_name("printSum(a:b:)")));
これはSwiftでもうまく機能します。
このKDocコメントをObjective-Cヘッダーにエクスポートする機能を試すには、-Xexport-kdoc
コンパイラオプションを使用します。コメントをエクスポートするGradleプロジェクトのbuild.gradle(.kts)
に次の行を追加します。
- Kotlin
- Groovy
kotlin {
targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
compilations.get("main").kotlinOptions.freeCompilerArgs += "-Xexport-kdoc"
}
}
kotlin {
targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget) {
compilations.get("main").kotlinOptions.freeCompilerArgs += "-Xexport-kdoc"
}
}
このYouTrack ticketを使用して、フィードバックをお寄せいただければ幸いです。
コンパイラのバグ修正
Kotlin/Nativeコンパイラでは、1.5.20で複数のバグ修正が行われました。完全なリストはchangelogで確認できます。
互換性に影響する重要なバグ修正があります。以前のバージョンでは、不正なUTF surrogate pairsを含む文字列定数は、コンパイル中に値を失っていました。現在、このような値は保持されます。アプリケーション開発者は1.5.20に安全にアップデートできます。何も壊れることはありません。ただし、1.5.20でコンパイルされたライブラリは、以前のコンパイラバージョンと互換性がありません。 詳細については、this YouTrack issueをご覧ください。
配列内のArray.copyInto()のパフォーマンス向上
ソースとデスティネーションが同じ配列の場合、Array.copyInto()
の動作が改善されました。このユースケースでは、メモリ管理の最適化により、コピーされるオブジェクトの数に応じて、最大20倍高速に完了するようになりました。
Kotlin/JS
1.5.20では、Kotlin/JSの新しいIR-based backendにプロジェクトを移行するのに役立つガイドを公開しています。
JS IR backendの移行ガイド
新しいmigration guide for the JS IR backendでは、移行中に発生する可能性のある問題を特定し、その解決策を提供しています。ガイドに記載されていない問題が見つかった場合は、issue trackerにご報告ください。
Gradle
Kotlin 1.5.20では、Gradleのエクスペリエンスを向上させる次の機能が導入されています。
kaptでのannotation processors classloadersのキャッシング
kaptでのannotation processors classloadersのキャッシングはExperimentalです。 いつでも削除または変更される可能性があります。評価目的でのみ使用してください。 YouTrackでフィードバックをお待ちしております。
kaptでannotation processorsのクラスローダーをキャッシュできる新しい実験的機能が追加されました。 この機能により、連続するGradle実行のkaptの速度を向上させることができます。
この機能を有効にするには、gradle.properties
ファイルで次のプロパティを使用します。
# positive value will enable caching
# use the same value as the number of modules that use kapt
kapt.classloaders.cache.size=5
# disable for caching to work
kapt.include.compile.classpath=false
kaptの詳細はこちら。
kotlin.parallel.tasks.in.projectビルドプロパティの非推奨
このリリースでは、Kotlinの並列コンパイルはGradle parallel execution flag --parallel
によって制御されます。
このフラグを使用すると、Gradleはタスクを同時に実行し、タスクのコンパイル速度を向上させ、リソースをより効率的に利用します。
kotlin.parallel.tasks.in.project
プロパティを使用する必要はなくなりました。このプロパティは非推奨となり、次のメジャーリリースで削除されます。
Standard library
Kotlin 1.5.20では、文字を扱ういくつかの関数のプラットフォーム固有の実装が変更され、その結果、プラットフォーム間で統一されました。
- Kotlin/NativeおよびKotlin/JSでのChar.digitToInt()でのすべてのUnicode数字のサポート。
- プラットフォーム間でのChar.isLowerCase()/isUpperCase()実装の統一。
Kotlin/NativeおよびKotlin/JSでのChar.digitToInt()でのすべてのUnicode数字のサポート
Char.digitToInt()
は、文字が表す10進数の数値値を返します。1.5.20より前は、この関数はKotlin/JVMでのみすべてのUnicode数字文字をサポートしていました。NativeおよびJSプラットフォームの実装では、ASCII数字のみがサポートされていました。
これからは、Kotlin/NativeとKotlin/JSの両方で、任意のUnicode数字文字に対してChar.digitToInt()
を呼び出して、その数値表現を取得できます。
fun main() {
val ten = '\u0661'.digitToInt() + '\u0039'.digitToInt() // ARABIC-INDIC DIGIT ONE + DIGIT NINE
println(ten)
}
プラットフォーム間でのChar.isLowerCase()/isUpperCase()実装の統一
関数Char.isUpperCase()
と
Char.isLowerCase()
は、文字の大文字と小文字に応じてブール値を返します。Kotlin/JVMの場合、実装はGeneral_Category
とOther_Uppercase
/Other_Lowercase
Unicode propertiesの両方をチェックします。
1.5.20より前は、他のプラットフォームの実装は異なり、一般的なカテゴリのみを考慮していました。 1.5.20では、実装がプラットフォーム間で統一され、両方のプロパティを使用して文字ケースを判断します。
fun main() {
val latinCapitalA = 'A' // has "Lu" general category
val circledLatinCapitalA = 'Ⓐ' // has "Other_Uppercase" property
println(latinCapitalA.isUpperCase() && circledLatinCapitalA.isUpperCase())
}