Kotlin 2.4.x 相容性指南
「保持語言現代化」與「舒適的更新」是 Kotlin 語言設計的基本原則。前者指出應移除阻礙語言演進的結構,後者則強調這類移除應事先進行充分溝通,以使程式碼遷移儘可能平滑。
雖然大多數語言變更已透過其他管道宣布(如更新日誌或編譯器警告),本文件對其進行了全面總結,為從 Kotlin 2.3 遷移到 Kotlin 2.4 提供完整參考。本文件還包含與工具相關的變更資訊。
基本術語
在本文件中,我們介紹了幾種相容性:
- 原始碼 (source):原始碼不相容的變更會導致原本可以正常編譯(無錯誤或警告)的程式碼無法再編譯。
- 二進位 (binary):如果兩個二進位構件相互替換不會導致載入或連結錯誤,則稱它們為二進位相容。
- 行為 (behavioral):如果在套用變更前後,同一個程式表現出不同的行為,則稱該變更為行為不相容。
請注意,這些定義僅針對純 Kotlin。從其他語言角度(例如 Java)看 Kotlin 程式碼的相容性不在本文件的討論範圍內。
語言
停止支援 -language-version=1.9 與 K1 編譯器
問題:KT-80590
組建:編譯器
不相容變更類型:原始碼
簡要摘要:從 Kotlin 2.4 開始,編譯器不再支援
-language-version=1.9。因此,K1 編譯器也不再受到支援。棄用週期:
- 2.2.0:使用
-language-version為 1.9 版時報告警告- 2.4.0:將警告提升為錯誤
禁止 Java 型別的彈性顯式可為 null 型別引數
問題:KTLC-284
組建:核心語言
不相容變更類型:原始碼
簡要摘要:先前在 Kotlin 中呼叫 Java API 時,編譯器可能會將顯式指定的可為 null 型別引數視為彈性型別引數。Kotlin 2.4.0 不再對可為 null 的型別引數套用此行為,因此編譯器現在會針對可能破壞型別安全或在執行時失敗的程式碼報告錯誤。
棄用週期:
- 2.2.0:針對被視為彈性型別的顯式指定可為 null 型別引數報告警告
- 2.4.0:將警告提升為錯誤
禁止針對絕對不相容型別進行恆為假的 is 檢查
問題:KTLC-365
組建:核心語言
不相容變更類型:原始碼
簡要摘要:編譯器現在會阻止毫無意義且恆為假的
is檢查,因為受檢型別絕對不相容。這使該行為與其他涉及不相容型別的操作保持一致。棄用週期:
- 2.0.0:針對絕對不相容型別的
is檢查報告警告- 2.4.0:將警告提升為錯誤
禁止在內嵌函式中公開具有較低可見性的型別與宣告
問題:KTLC-283
組建:核心語言
不相容變更類型:原始碼
簡要摘要:編譯器現在會阻止內嵌函式公開可見性低於內嵌函式本身的型別與宣告。
棄用週期:
- 2.3.0:針對在內嵌函式中公開較低可見性的型別與宣告報告警告
- 2.4.0:將警告提升為錯誤
變更註解的預設使用處目標選取
問題:KTLC-391
組建:核心語言
不相容變更類型:二進位
簡要摘要:Kotlin 2.4.0 更新了將註解傳遞給參數、屬性與欄位的預設規則。這可能會影響重新編譯後的註解處理、反射與二進位元資料。當您未指定使用處目標時,編譯器現在會優先使用
param與property(如果適用),且僅在property不適用時才使用field。您可以顯式指定使用處目標,例如使用
@param:Annotation代替@Annotation。若要針對整個專案使用先前的預設規則,請在組建檔案中加入-Xannotation-default-target=first-only。棄用週期:
- 2.2.0:當新的預設規則改變選定的使用處目標時報告警告
- 2.4.0:啟用新的預設規則
禁止隱式參照不可存取的型別
問題:KTLC-384
組建:核心語言
不相容變更類型:原始碼
簡要摘要:使用隱式參照來自間接相依性之不可存取型別的宣告,現在會導致錯誤。
若要遷移,請對宣告該不可存取型別的模組新增顯式相依性,或更新中間層 API 以避免公開該型別。
棄用週期:
- 2.3.0:針對隱式參照不可存取的型別報告警告
- 2.4.0:將警告提升為錯誤
強制執行 Jakarta 可為 null 性註解
問題:KTLC-285
組建:核心語言
不相容變更類型:原始碼
簡要摘要:編譯器現在會針對使用
jakarta.annotation.Nullable或jakarta.annotation.Nonnull的 Java 宣告,在 Kotlin 中強制執行宣告的可為 null 性。如果您將這些註解標記為可為 null 的 Java 宣告指派給不可為 null 的 Kotlin 型別,編譯器將報告錯誤。棄用週期:
- 2.2.0:針對帶有 Jakarta 可為 null 性註解的 Java 宣告中的可為 null 性不符報告警告
- 2.4.0:將警告提升為錯誤
報告可呼叫參照限定詞中位置錯誤的型別引數
問題:KTLC-388
組建:核心語言
不相容變更類型:原始碼
簡要摘要:編譯器現在會檢查可呼叫參照的左側,如果內部類別在限定詞的錯誤部分包含型別引數,則會報告警告。
若要遷移,請更新參照,使每個型別引數都屬於宣告它的類別。例如,應撰寫完整型別
Outer<Int>.Inner<String>::toString,而非Inner<String, Int>::toString。棄用週期:
- 2.4.0:當可呼叫參照左側的型別引數屬於限定詞的其他部分時報告警告
針對具有可為 null 上限之具體化型別參數的類別常值報告錯誤
問題:KTLC-370
組建:核心語言
不相容變更類型:原始碼
簡要摘要:當您在一個型別來自具有可為 null 上限之具體化型別參數的運算式上使用
::class時,編譯器現在會報告錯誤。如果您在此類運算式上使用::class,請先透過顯式 null 檢查或!!運算子將值變為非 null。棄用週期:
- 2.3.0:當在型別來自具有可為 null 上限之具體化型別參數的運算式上使用
::class時報告警告- 2.4.0:將警告提升為錯誤
禁止在匿名物件宣告前進行初始化
問題:KTLC-290
組建:核心語言
不相容變更類型:原始碼
簡要摘要:現在當您在匿名物件的
init區塊中,於宣告屬性之前初始化該屬性時,Kotlin 會報告錯誤。棄用週期:
- 2.2.20:當匿名物件中的
init區塊在屬性宣告前初始化屬性時報告警告- 2.4.0:將警告提升為錯誤
對包含非抽象 Java 密封類別的 when 運算式強制執行詳盡性檢查
問題:KTLC-366
組建:核心語言
不相容變更類型:原始碼
簡要摘要:當您對非抽象 Java 密封類別使用
when運算式時,Kotlin 現在會更嚴格地檢查詳盡性,要求提供else分支或與該密封類別本身匹配的分支。先前,儘管 Java 密封類別本身可以直接具現化,Kotlin 仍可能將此類when運算式視為已詳盡。棄用週期:
- 2.3.0:針對包含非抽象 Java 密封類別的非詳盡
when運算式報告警告- 2.4.0:將警告提升為錯誤
禁止在參數過多的 getValue() 與 setValue() 函式上使用 operator 修飾詞
問題:KTLC-289
組建:核心語言
不相容變更類型:原始碼
簡要摘要:當您為
getValue()或setValue()函式標記operator修飾詞時,編譯器現在會檢查它們是否具有要求的參數數量。getValue()函式必須正好有兩個參數,而setValue()函式必須正好有三個。若要遷移,請移除operator修飾詞或更改函式簽章。棄用週期:
- 2.2.20:針對參數過多的
operatorgetValue()與setValue()函式報告警告- 2.4.0:將警告提升為錯誤
禁止泛型呼叫中不一致的型別引數
問題:KTLC-373
組建:核心語言
不相容變更類型:原始碼
簡要摘要:當您在泛型呼叫中指定型別引數時,如果一個型別引數違反了取決於另一個型別引數的上限約束,編譯器現在會報告錯誤。如果型別參數相互依賴,請使用符合這些約束的型別引數,例如使用
Container<Alpha, AlphaKey>()而非Container<Alpha, BetaKey>()。棄用週期:
- 2.3.0:當泛型呼叫中的顯式型別引數違反型別參數間的上限約束時報告警告
- 2.4.0:將警告提升為錯誤
棄用對 javaClass 屬性的參照
問題:KTLC-375
組建:Kotlin/JVM
不相容變更類型:原始碼
簡要摘要:Kotlin 2.4.0 棄用了對
javaClass屬性的屬性參照,以減少與::class.java的混淆。請使用.javaClass獲取物件的執行時 Java 類別,或使用::class.java獲取 Java 類別參照。棄用週期:
- 2.4.0:針對
javaClass屬性的屬性參照報告警告
針對需要選擇性加入的隱式列舉建構函式呼叫報告錯誤
問題:KTLC-359
組建:核心語言
不相容變更類型:原始碼
簡要摘要:現在當列舉成員隱式呼叫需要選擇性加入(opt-in)的列舉主建構函數時,Kotlin 會報告錯誤。若要遷移,請在列舉類別或每個呼叫該建構函式的列舉成員上新增
@OptIn。棄用週期:
- 2.2.20:當列舉成員隱式呼叫需要選擇性加入的列舉主建構函數時報告警告
- 2.4.0:將警告提升為錯誤
禁止在列舉成員上使用 inline 修飾詞
問題:KTLC-361
組建:核心語言
不相容變更類型:原始碼
簡要摘要:現在當您在列舉成員上使用
inline修飾詞時,Kotlin 會報告錯誤。棄用週期:
- 2.3.0:當在列舉成員上使用
inline修飾詞時報告警告- 2.4.0:將警告提升為錯誤
禁止在註解呼叫與參數預設值之外使用陣列常值
問題:KTLC-369
組建:核心語言
不相容變更類型:原始碼
簡要摘要:在註解呼叫與註解參數預設值之外使用陣列常值現在會導致錯誤。若要遷移,請使用
arrayOf(...),例如使用Roles(arrayOf("admin", "user"))而非Roles(["admin", "user"])。棄用週期:
- 2.3.0:針對註解呼叫與註解參數預設值之外的陣列常值報告警告
- 2.4.0:將警告提升為錯誤
在命令列編譯器模式下禁止使用 _root_ide_package_
問題:KTLC-378
組建:編譯器
不相容變更類型:原始碼
簡要摘要:在命令列編譯器模式下使用僅限 IDE 的
_root_ide_package_限定詞現在會導致錯誤。棄用週期:
- 2.3.20:針對命令列編譯器模式下的
_root_ide_package_參照報告警告- 2.4.0:將警告提升為錯誤
修正帶有可變參數轉換之函式參照的相等性
問題:KTLC-385
組建:Kotlin/JVM
不相容變更類型:行為
簡要摘要:Kotlin/JVM 現在將具有不同轉換的函式參照視為不相等。先前,當同一個函式參照也使用其他轉換時,Kotlin/JVM 在相等性檢查中會忽略可變參數轉換,因此
getDefault(::foo) == getDefaultAndVararg(::foo)可能傳回true,即便只有一方使用了可變參數轉換。棄用週期:
- 2.4.0:引入新行為
對伴隨物件存取強制執行選擇性加入
問題:KTLC-386
組建:核心語言
不相容變更類型:原始碼
簡要摘要:當類別名稱參照解析為需要選擇性加入的伴隨物件時,Kotlin 現在會報告選擇性加入錯誤。例如,如果
C解析為標記有選擇性加入註解的伴隨物件,則val p = C需要選擇性加入。棄用週期:
- 2.3.20:當伴隨物件存取需要選擇性加入時報告警告
- 2.4.0:針對
ERROR層級的選擇性加入要求將警告提升為錯誤
報告來自具有巢狀泛型引數之超型別的型別不符
問題:KTLC-372
組建:核心語言
不相容變更類型:原始碼
簡要摘要:當編譯器偵測到涉及具有巢狀泛型引數之超型別的型別不符時,現在會報告錯誤。先前編譯器可能會漏掉此不符,導致稍後發生
ClassCastException。若要遷移,請使用與接收者泛型型別匹配的型別引數,或移除顯式型別引數以便編譯器進行推論。棄用週期:
- 2.4.0:針對涉及具有巢狀泛型引數之超型別的型別不符報告錯誤
禁止包含不可存取宣告的推論型別
問題:KTLC-363
組建:核心語言
不相容變更類型:原始碼
簡要摘要:使用包含在當前作用域內不可存取宣告的推論型別現在會導致錯誤。
棄用週期:
- 2.3.0:當推論型別包含在當前作用域內不可存取的宣告時報告警告
- 2.4.0:將警告提升為錯誤
標準函式庫
棄用 kotlin.io.readLine() 函式
問題:KTLC-394
組建:kotlin-stdlib
不相容變更類型:原始碼
簡要摘要:
kotlin.io.readLine()函式已被棄用。請使用readln()函式代替readLine()!!,並使用readlnOrNull()函式代替readLine()。棄用週期:
- 2.4.0:使用
kotlin.io.readLine()時報告警告
棄用 AbstractCoroutineContextKey 及相關 API
問題:KT-84970
組建:kotlin-stdlib
不相容變更類型:原始碼
簡要摘要:
AbstractCoroutineContextKey類別及其相關 API 自 Kotlin 1.3 起即為實驗性功能,且事實證明容易出錯。因此,該類別及相關的getPolymorphicElement()與minusPolymorphicKey()函式已被棄用。棄用週期:
- 2.4.0:使用已棄用的 API 時報告警告
變更無限邊界下的 Random.nextDouble() 契約
問題:KT-84368
組建:kotlin-stdlib
不相容變更類型:行為
簡要摘要:
Random.nextDouble(until)的文件契約現在要求until邊界必須為有限值。請改用有限邊界。棄用週期:
- 2.4.0:啟用新行為
工具
棄用舊版 Kotlin/JS 編譯器類型選取 API
組建:Gradle
不相容變更類型:原始碼
簡要摘要:Kotlin 2.4.0 移除了與選取舊版 Kotlin/JS 編譯器類型相關的已棄用 Gradle API。
此外,
KotlinJsCompilerType列舉以及帶有編譯器類型參數的KotlinProjectExtension.js()多載已被棄用。若要遷移,請從js()目標宣告中移除編譯器類型引數,並改用js {}區塊。棄用週期:
- 1.8.0:棄用舊版 Kotlin/JS 編譯器類型常數
- 2.4.0:移除已棄用的舊版編譯器類型 API,並在使用
KotlinJsCompilerType或帶有編譯器類型參數的KotlinProjectExtension.js()多載時報告警告
棄用 Kotlin Android 擴充套件中的 sourceSets
問題:KT-74451
組建:Gradle
不相容變更類型:原始碼
簡要摘要:
KotlinAndroidProjectExtension中的sourceSets屬性已被棄用。若要遷移,請改由 Android Gradle 外掛程式的android { sourceSets { ... } }區塊配置原始碼集。棄用週期:
- 2.4.0:從
KotlinAndroidProjectExtension存取sourceSets時報告警告
移除 Kotlin/Native Apple 框架的可取用組態
組建:Gradle
不相容變更類型:原始碼
簡要摘要:Kotlin 2.4.0 移除了將 Kotlin/Native Apple 框架公開為傳出構件的已產生可取用 Gradle 組態。
棄用週期:
- 2.4.0:移除 Kotlin/Native Apple 框架的可取用組態
從 Kotlin Gradle 外掛程式中移除已棄用的任務、編譯與 DSL API
問題:KT-85509
組建:Gradle
不相容變更類型:原始碼
簡要摘要:Kotlin 2.4.0 移除了以下已棄用的 Kotlin Gradle 外掛程式 API:
編譯任務配置 API:
KotlinJvmCompile.parentKotlinOptionsKotlinJvmCompile.moduleNameKotlinJvmFactory.createKotlinJvmOptions()KotlinCompile與Kotlin2JsCompile任務中的BaseKotlinCompile.moduleNameKotlin 多平台階層與目標 API:
DeprecatedKotlinTargetHierarchyDslKotlinMultiplatformExtension.targetHierarchyKotlinTargetComponent.sourcesArtifactsKotlinTarget.sourceSetsKotlinHierarchyBuilder.withoutCompilations()KotlinHierarchyBuilder.filterCompilations()KotlinHierarchyBuilder.withWasm()KotlinCompilation.defaultSourceSetNameKotlin 編譯任務 API:
KotlinCompilation.compileKotlinTaskProviderKotlinCompilation.compileKotlinTaskKotlin 相依性處理器 API:
KotlinDependencyHandler.enforcedPlatform()KotlinDependencyHandler.platform()其他已棄用的任務與延伸 API:KaptExtension.processorsKotlinTest.excludesKotlinTest.fileResolverKotlinTest.execHandleFactoryIncrementalSyncTask.destinationDir若要遷移,請移除對這些 API 的使用,並改用棄用診斷訊息中建議的替代方案。
棄用週期:
- 2.4.0:移除已棄用的 API
棄用顯式縮減後的類別路徑快照配置
問題:KT-75837
組建:建置工具 API
不相容變更類型:原始碼
簡要摘要:
ClasspathSnapshotBasedIncrementalCompilationApproachParameters中的shrunkClasspathSnapshot配置參數已被棄用。縮減後的類別路徑快照是一個內部增量編譯快取,因此編譯器現在會自動在增量編譯器中繼資料workingDirectory下建立並管理它。若要遷移,請使用自動管理的快照檔案,而非向shrunkClasspathSnapshot傳遞值。棄用週期:
- 2.4.0:使用
shrunkClasspathSnapshot時報告警告
移除多餘的 ABI 驗證 Gradle DSL 元素
問題:KT-80685
組建:Gradle
不相容變更類型:原始碼
簡要摘要:Kotlin 2.4.0 簡化了 ABI 驗證 Gradle DSL 並移除了多餘的配置項目。若要遷移,請直接在
abiValidation {}中配置報告設定,而非abiValidation { legacyDump { ... } };移除abiValidation { klib { enabled = ... } };並使用keepLocallyUnsupportedTargets代替klib.keepUnsupportedTargets。棄用週期:
- 2.4.0:移除多餘的 ABI 驗證 DSL 元素
棄用過時的 Compose 編譯器 Gradle 外掛程式選項
問題:KT-85343
組建:Gradle
不相容變更類型:原始碼
簡要摘要:在 Kotlin 2.4.0 中,以下已棄用的 Compose 編譯器 Gradle 外掛程式選項在使用時現在會報告錯誤:
generateFunctionKeyMetaClassesenableIntrinsicRememberenableNonSkippingGroupOptimizationenableStrongSkippingModestabilityConfigurationFileComposeFeatureFlag.StrongSkippingComposeFeatureFlag.IntrinsicRemember請改用
featureFlags代替已棄用的特性選項,並使用stabilityConfigurationFiles代替stabilityConfigurationFile。棄用週期:
- 2.0.20:針對
enableIntrinsicRemember、enableNonSkippingGroupOptimization與enableStrongSkippingMode報告警告- 2.1.0:針對
stabilityConfigurationFile報告警告- 2.4.0:將警告提升為錯誤
針對過時的 Kotlin/Native Gradle 任務 API 報告錯誤
問題:KT-85510
組建:Gradle
不相容變更類型:原始碼
簡要摘要:以下已棄用的 Kotlin/Native Gradle 任務 API 在使用時現在會報告錯誤:
AbstractKotlinNativeCompile屬性:
additionalCompilerOptionslanguageSettingsprogressiveMode
KotlinNativeCompile屬性:
moduleNamekonanDataDirkonanHomelanguageVersionapiVersionenabledLanguageFeaturesoptInAnnotationsInUseadditionalCompilerOptions
CInteropProcess屬性:
outputFilekonanDataDirkonanHomedefFile
KotlinNativeLink屬性:
languageSettingsadditionalCompilerOptionskonanDataDirkonanHome此外,
KotlinNativeLink.compilation屬性已被移除。棄用週期:
- 2.4.0:針對已棄用的 Kotlin/Native Gradle 任務 API 報告錯誤,並移除
KotlinNativeLink.compilation屬性
