2025.1 版本已經發布,在此之前我們就聊過該版本的 《Terminal 又發布全新重構版本》,而現在 2025.1 中的 K2 模式也成為了默認選項。
可以預見,這個版本可能會包含不少大坑,為下個 Android Studio 祈禱。
首先有一點可以確定,隨著 K2 模式成為默認選項,雖然 K1模式仍可使用,但后續 K1 將不再支持新語言特性和 IDE 優化,所以在 2025.1 里,你依然可以在 Language & FRameworks > Kotlin
里關閉 K2 模式,但是只能說「逃得了一時是一時」:
“K2” 對應的是 Kotlin 插件包含用于代碼分析的 K2 Kotlin 編譯器的內部版本,而 K1 模式使用 K1 編譯器,IntelliJ IDEA 中內置的 Kotlin 編譯器版本完全獨立于項目構建文件中指定的版本,但它可能會影響項目中支持的 Kotlin 版本范圍。
在之前的《K2 模式已發布穩定版》我們提到過,IntelliJ IDEA 的 K2 模式并不依賴于項目構建設置中指定的 Kotlin 編譯器版本,K2 模式代表 IDE 中對 Kotlin 編輯場景支持的幾乎完全重寫,而使用 K2 編譯器可以帶來:
- 高達 94% 的編譯速度提升
- 在初始化階段的速度提高了 488%
- 與之前的編譯器相比,Kotlin K2 編譯器在分析階段的速度提高了 376%
- ····
所以基于 K2 編譯器能力的 K2 模式,在 Kotlin 代碼分析、補全和導航速度方面取得了巨大進步,這體現在全新 IDE 下就是:
- 提高代碼分析的性能(如高亮、補全速度)
- 更快的查找和跳轉
- 支持 Kotlin 2.0 及以上版本的新語言特性
而 IDE 一直以來都深度依賴 K1 ,所以其實在遷移到 K2 的過程中,會有大量的重寫和功能重構,這也是 K2 到現在還一直需要打磨的原因。
而在 K1 到 K2 的變化里,其中最大的就是全新的 Kotlin Analysis API ,它提供了一種清晰穩定的方式來訪問代碼信息,并且不需要依賴編譯器內部結構。
Kotlin Analysis API 在 K2 模式里采用模塊化架構,支持 IDE 功能(如補全、檢查)獨立調用編譯器的特定分析階段(如解析或類型檢查),避免不必要的全量分析,從而提升性能。
K2 編譯器放棄了 K1 中隱式的 laziness,轉而采用顯式的分階段代碼分析架構, K2 編譯器會分階段分析代碼(如 SUPER_TYPES 計算類的 supertypes ,TYPES 處理函數 signature types),每個階段逐步為抽象語法樹(AST)添加語義信息。
另外,在 K1 模式里 Kotlin Analysis API 的分析操作通常受限于單一的全局解析鎖(global resolution lock),例如 Find Usages 等功能會持有全局鎖,導致其他功能(如代碼高亮、補全)無法并行執行,造成性能瓶頸。
而 K2 編譯器的解析邏輯是并發容忍(concurrency-tolerant),Kotlin Analysis API 利用這一特性,消除了全局鎖,API 現在支持同時分析多個聲明(declarations),即使在復雜場景(如兩個函數相互調用)中也能高效處理:
雖然 K2 編譯器目前還是使用單線程分析(因為多模塊并行編譯已利用多核),但是目前的并發容忍設計為未來的多線程分析奠定了基礎,后續 Kotlin Analysis API 可無縫適配。
而在插件遷移適配上,Kotlin Analysis API 也起到了很大作用,它封裝了所有復雜的解析邏輯,并提供具有清晰且可預測行為的記錄抽象,開發者只需請求他需要的語義代碼信息片段,API 會處理所有延遲和并行分析并緩存結果。
例如要獲取表達式類型,開發者只需調用庫提供的 KtExpression.expressionType
擴展屬性 ,如果類型尚不清楚,則將自動分析包含聲明的 body :
fun KtExpression.hasStringType(): Boolean {analyze(this) {return expressionType == builtinTypes.string}
}
而事實上,不管你的項目是不是 K2 ,都可以享受到新 IDE 在 K2 模式下帶來的性能提升,而如果你開發或使用的是插件,那么可能會需要將部分依賴舊的 Kotlin 插件進行遷移,例如:
- 舊的編譯器 API
SPECIAL_ANNOTATION_NAME = FqName("my.app.Special")fun hasAnnotation(declaration: KtDeclaration): Boolean {val bindingContext = declaration.analyze()val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration]?: return falsereturn descriptor.annotations.hasAnnotation(SPECIAL_ANNOTATION_NAME)
}
- 新 Analysis API
val SPECIAL_ANNOTATION_CLASS_ID = ClassId.fromString("my/app/Special")fun hasAnnotation(declaration: KtDeclaration): Boolean {analyze(declaration) {return SPECIAL_ANNOTATION_CLASS_ID in declaration.symbol.annotations}
}
另外,就像前面說的,關于一些新特性,比如 Kotlin 2.1 的新支持就會僅限于 K2 模式的 IDE,例如:
- Non-local 的 break/continue :
fun processList(elements: List<Int>): Boolean {for (element in elements) {val variable = element.nullableMethod() ?: run {log.warning("Element is null or invalid, continuing...")continue // 在早期不能在 forEach 的 lambda 中直接使用 continue}if (variable == 0) return true // If variable is zero, return true}return false
}
- 在 when 里使用 guard condition:
sealed interface Animal {data class Cat(val mouseHunter: Boolean) : Animal {fun feedCat() {}}data class Dog(val breed: String) : Animal {fun feedDog() {}}
}fun feedAnimal(animal: Animal) {when (animal) {// Branch with only the primary condition. Returns `feedDog()` when `Animal` is `Dog`is Animal.Dog -> animal.feedDog()// Branch with both primary and guard conditions. Returns `feedCat()` when `Animal` is `Cat` and is not `mouseHunter`is Animal.Cat if !animal.mouseHunter -> animal.feedCat()// Returns "Unknown animal" if none of the above conditions matchelse -> println("Unknown animal")}
}
- 多美元字符串插值,通過初始
$$
表示需要兩個美元符號 ($$
) 來觸發插值,防止$schema
、$id
和$dynamicAnchor
被解釋為插值標記:
val KClass<*>.jsonSchema : Stringget() = $$"""{"$schema": "https://json-schema.org/draft/2020-12/schema","$id": "https://example.com/product.schema.json","$dynamicAnchor": "meta""title": "$${simpleName ?: qualifiedName ?: "unknown"}","type": "object"}"""
最后,未來即將更新的 Android Studio 也會一樣默認開始 K2 模式,所以作為 Android 開發,對于下一個版本的 AS 更新還需要慎重,因為你也不知道會有什么坑在等著你。
當然,最后還是要強調:
- K2 編譯器是 Kotlin 語言的新一代編譯器
- K2 Mode 是 IntelliJ IDEA 的一種運行模式
K2 Mode 是 IDEA 利用 K2 編譯器的前端(解析和語義分析部分)來增強 IDE 的 Kotlin 代碼理解能力,但不直接參與項目的實際編譯,功能范圍僅限于 IDE 的交互體驗。
所以理論上,你項目用 K1,也不影響你體驗 K2 Mode ,但是如果你項目使用 K2,那么強烈建議開始 K2 Mode 來體驗全新的特性。
那么,你已經體驗過 K2 模式了么?
參考資料
-
https://blog.jetbrains.com/idea/2025/04/k2-mode-in-intellij-idea-2025-1-current-state-and-faq/
-
https://blog.jetbrains.com/idea/2025/04/the-story-behind-k2-mode-and-how-it-works/