Kotlin兼容性

本頁介紹 Kotlin 不同版本以及子系統的兼容性保證。

兼容性詞彙表

兼容性意味着回答這個問題:對於給定的兩個版本的 Kotlin(例如,1.2 和 1.1.5),爲一個版本編寫的代碼可以與另一個版本一起使用嗎?下面的列表解釋了不同版本對的兼容模式。請注意,如果版本號較小(即使發佈時間晚於版本號較大的版本)那麼版本較舊。對於「舊版本」我們使用 OV,對於「新版本」使用 NV。

  • C——完全兼容(Full Compatibility)
    • 語言
      • 無語法改動(除去 bug*)
      • 可能添加或刪除新的警告/提示
    • API(kotlin-stdlib-*kotlin-reflect-*)
      • 無 API 改動
      • 可能添加/刪除帶有 WARNING 級的棄用項
    • 二進制(ABI)
      • 運行時:二進制可以互換使用
      • 編譯:二進制可以互換使用
  • BCLA——語言和 API 向後兼容(Backward Compatibility for the Language and API)
    • 語言
      • 可能會在 NV 中刪除 OV 中已棄用的語法
      • 除此之外,OV 中可編譯的所有代碼都可以在 NV 中編譯(除去 bug*)
      • 可能在 NV 中添加新語法
      • 在 NV 中可以提升 OV 的一些限制
      • 可能添加或刪除新的警告/提示
    • API(kotlin-stdlib-*kotlin-reflect-*)
      • 可能添加新的 API
      • 可能添加/刪除帶有 WARNING 級的棄用項
      • WARNING 級的棄用項可能在 NV 中提升到 ERROR 級或者 HIDDEN
  • BCB——二進制向後兼容(Backward Compatibility for Binaries)
    • 二進制(ABI)
      • 運行時:NV 的二進制可以在 OV 的二進制工作的任何地方使用
      • NV 編譯器:針對 OV 二進制編譯的代碼可針對 NV 二進制編譯
      • OV 編譯器可能不接受 NV 二進制(例如,展示較新語言特性或 API 的二進制)
  • BC——完全向後兼容(Full Backward Compatibility)
    • BC = BCLA & BCB
  • EXP——實驗性的功能(Experimental feature)
    • 參見下文
  • NO——無兼容性保證(No compatibility guarantees)
    • 我們會盡力提供順利的遷移,但不能給出任何保證
    • 爲每個不兼容的子系統單獨規劃遷移

* 除去 bugs 無改動意味着如果發現一個重要的 bug(例如在編譯器診斷或其他地方),修復它可能會引入一個破壞性改動,但我們總是非常小心對待這樣的改動。

Kotlin 發行版的兼容性保證

JVM 平臺的 Kotlin

  • 補丁版本更新(例如1.1.X)完全兼容
  • 次版本更新(例如1.X)向後兼容

Kotlin

1.0

1.0.X

1.1

1.1.X

2.0

1.0

-

C

BC

BC

?

1.0.X

C

-

BC

BC

?

1.1

BC

BC

-

C

?

1.1.X

BC

BC

C

-

?

2.0

?

?

?

?

-

JS 平臺的 Kotlin:從 Kotlin 1.1 開始,補丁版本和次版本更新爲語言和 API 提供向後兼容性(BCLA),但沒有 BCB。

Kotlin

1.0.X

1.1

1.1.X

2.0

1.0.X

-

EXP

EXP

EXP

1.1

EXP

-

BCLA

?

1.1.X

EXP

BCLA

-

?

2.0

EXP

?

?

-

Kotlin Scripts:補丁版本和次版本更新爲語言和 API 提供向後兼容性(BCLA),但沒有 BCB。

跨平臺兼容性

Kotlin 可用於多個平臺(JVM/Android、JavaScript 以及即將推出的本地平臺)。每個平臺都有自己的特殊性(例如 JavaScript 沒有適當的整數),因此我們必須相應地調整語言。我們的目標是提供合理的代碼可移植性,而不會犧牲太多。

每個平臺都可能具有特定的語言擴展(例如 JVM 的平臺類型和 JavaScript 的動態類型)或限制(例如 JVM 上與重載相關的限制),但核心語言保持不變。

標準庫提供了在所有平臺上可用的核心 API,我們努力使這些 API 在每個平臺上以相同的方式工作。除此之外,標準庫提供了平臺相關的擴展(例如,JVM 的java.io 或 JavaScript 的 js())以及一些可以統一調用但工作方式不同的 API(例如 JVM 和 JavaScript 的正則表達式)。

實驗性的功能

實驗性的功能,如 Kotlin 1.1 中的協程,可以從上面列出的兼容模式中豁免。這類功能需要選擇性加入(opt-in)來使用纔沒有編譯器警告。實驗性的功能至少向後兼容補丁版本更新,但我們不保證任何次版本更新的兼容性(會盡可能提供遷移幫助)。

Kotlin

1.1

1.1.X

1.2

1.2.X

1.1

-

BC

NO

NO

1.1.X

BC

-

NO

NO

1.2

NO

NO

-

BC

1.2.X

NO

NO

BC

-

EAP 構建版

我們發佈早期訪問預覽(Early Access Preview,EAP)構建版到特殊渠道,該社區的早期採用者可以試用它們並提供反饋。這樣的構建不提供任何兼容性保證(儘管我們盡最大努力保持它們與發行版以及彼此之間的合理的兼容性)。這類構建版的質量預期也遠低於發行版。Beta 測試版本也屬於這一類別。

重要注意事項:通過 EAP 爲 1.X(例如 1.1.0-eap-X)編譯的所有二進制文件會被編譯器發行版版本拒絕。我們不希望預發佈版本編譯的任何代碼在穩定版本發佈後保留。這不涉及補丁版本的 EAP(例如 1.1.3-eap-X),這些 EAP 產生具有穩定 ABI 的構建。

兼容性模式

當一個大團隊遷移到一個新版本時,當一些開發人員已經更新、而其他人沒有時,可能會在某個時候出現「不一致的狀態」。爲了防止前者編寫和提交別人可能無法編譯的代碼,我們提供了以下命令行開關(在 IDE 以及 Gradle/Maven 中也可用):

  • -language-version X.Y——Kotlin 語言版本 X.Y 的兼容性模式,對其後出現的所有語言功能報告錯誤
  • -api-version X.Y——Kotlin API 版本 X.Y 的兼容性模式,對使用來自 Kotlin 標準庫(包括編譯器生成的代碼)的新版 API 的所有代碼報告錯誤。

二進制兼容性警告

如果使用 NV Kotlin 編譯器並在 classpath 中配有 OV 標準庫或 OV 反射庫,那麼可能是項目配置錯誤的跡象。
爲了防止編譯期或運行時出現意外問題,我們建議要麼將依賴關係更新到 NV,要麼明確指定 API 版本/語言版本參數。
否則編譯器會檢測到某些東西可能出錯,並報告警告。

例如,如果 OV = 1.0 且 NV = 1.1,你可能觀察到以下警告之一:

Runtime JAR files in the classpath have the version 1.0, which is older than the API version 1.1. 
Consider using the runtime of version 1.1, or pass '-api-version 1.0' explicitly to restrict the 
available APIs to the runtime of version 1.0.

這意味着你針對版本 1.0 的標準庫或反射庫使用 Kotlin 編譯器 1.1。這可以通過不同的方式處理:

  • 如果你打算使用 1.1 標準庫中的 API 或者依賴於這些 API 的語言特性,那麼應將依賴關係升級到版本 1.1。
  • 如果你想保持你的代碼與 1.0 標準庫兼容,你可以傳參 -api-version 1.0
  • 如果你剛剛升級到 kotlin 1.1,但不能使用新的語言功能(例如,因爲你的一些隊友可能沒有升級),你可以傳參 -language-version 1.0,這會限制所有的 API 和語言功能到 1.0。
Runtime JAR files in the classpath should have the same version. These files were found in the classpath:
    kotlin-reflect.jar (version 1.0)
    kotlin-stdlib.jar (version 1.1)
Consider providing an explicit dependency on kotlin-reflect 1.1 to prevent strange errors
Some runtime JAR files in the classpath have an incompatible version. Consider removing them from the classpath

這意味着你對不同版本的庫有依賴性,例如 1.1 標準庫和 1.0 反射庫。爲了防止在運行時出現微妙的錯誤,我們建議你使用所有 Kotlin 庫的相同版本。在本例中,請考慮對 1.1 反射庫添加顯式依賴關係。

Some JAR files in the classpath have the Kotlin Runtime library bundled into them. 
This may cause difficult to debug problems if there's a different version of the Kotlin Runtime library in the classpath. 
Consider removing these libraries from the classpath

這意味着在 classpath 中有一個庫,它不是作爲 Gradle/Maven 依賴項而依賴 Kotlin 標準庫,而是與它分佈在同一個構件中(即是被捆綁的)。這樣的庫可能會導致問題,因爲標準構建工具不認爲它是 Kotlin 標準庫的實例,因此它不受依賴版本解析機制的限制,你可以在 classpath 找到同一個庫的多個版本。請考慮聯繫這樣的庫的作者,並提出使用 Gradle/Maven 依賴取代的建議。