Kotlin 1.4 兼容性指南
保持语言的现代性 和 舒适的更新 是 Kotlin 语言设计的根本原则。前者表示应该移除那些阻碍语言发展的结构,后者表示应该提前充分沟通这些移除,以使代码迁移尽可能平滑。
虽然大多数语言变更已经通过其他渠道宣布,如更新日志或编译器警告,但本文档将它们全部汇总,为从 Kotlin 1.3 迁移到 Kotlin 1.4 提供完整的参考。
基本术语
在本文档中,我们引入了几种兼容性:
- source(源码): source-incompatible change(源码不兼容变更)会阻止原本编译正常(没有错误或警告)的代码再也无法编译
- binary(二进制): 如果交换两个二进制工件不会导致加载或链接错误,则称它们是 binary-compatible(二进制兼容的)
- behavioral(行为): 如果同一个程序在应用变更前后表现出不同的行为,则称该变更是 behavioral-incompatible(行为不兼容的)
请记住,这些定义仅适用于纯 Kotlin。 从其他语言角度(例如,从 Java)来看,Kotlin 代码的兼容性不在本文档的范围内。
语言和标准库
in
中缀运算符和 ConcurrentHashMap
的意外行为
问题: KT-18053
组件: 核心语言
不兼容变更类型: 源码
简短摘要: Kotlin 1.4 将禁止自动运算符
contains
来自用 Java 编写的java.util.Map
的实现者弃用周期:
- < 1.4: 在调用点为有问题的运算符引入警告
- >= 1.4: 将此警告提升为错误, 可以使用
-XXLanguage:-ProhibitConcurrentHashMapContains
暂时恢复到 1.4 之前的行为
禁止从公共内联成员访问受保护的成员
问题: KT-21178
组件: 核心语言
不兼容变更类型: 源码
简短摘要: Kotlin 1.4 将禁止从公共内联成员访问受保护的成员。
弃用周期:
- < 1.4: 在调用点为有问题的用例引入警告
- 1.4: 将此警告提升为错误, 可以使用
-XXLanguage:-ProhibitProtectedCallFromInline
暂时恢复到 1.4 之前的行为
具有隐式接收者的调用上的 Contracts(契约)
问题: KT-28672
组件: 核心语言
不兼容变更类型: 行为
简短摘要: 来自 Contracts(契约)的智能类型转换将在 1.4 中对具有隐式接收者的调用可用
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-ContractsOnCallsWithImplicitReceiver
暂时恢复到 1.4 之前的行为
浮点数比较的不一致行为
问题: KT-22723
组件: 核心语言
不兼容变更类型: 行为
简短摘要: 自 Kotlin 1.4 以来,Kotlin 编译器将使用 IEEE 754 标准来比较浮点数
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-ProperIeee754Comparisons
暂时恢复到 1.4 之前的行为
在泛型 lambda 中的最后一个表达式上没有智能类型转换
问题: KT-15020
组件: 核心语言
不兼容变更类型: 行为
简短摘要: 自 1.4 以来,lambda 中最后一个表达式的智能类型转换将得到正确应用
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
不要依赖 lambda 参数的顺序来强制将结果转换为 Unit
问题: KT-36045
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,lambda 参数将被独立解析,而不会隐式强制转换为
Unit
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
原始类型和整数文本类型之间的错误公共超类型导致不健全的代码
问题: KT-35681
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,原始
Comparable
类型和整数文本类型之间的公共超类型将更具体弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
由于几个相等的类型变量使用不同的类型实例化,导致类型安全问题
问题: KT-35679
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,Kotlin 编译器将禁止使用不同的类型实例化相等的类型变量
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
由于 intersection types(交集类型)的不正确子类型化导致的类型安全问题
问题: KT-22474
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 在 Kotlin 1.4 中,intersection types(交集类型)的子类型化将被改进,以更正确地工作
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
在 lambda 表达式中的空 when
表达式没有类型不匹配
问题: KT-17995
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,如果空
when
表达式用作 lambda 中的最后一个表达式,则会出现类型不匹配弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
对于 lambda 表达式,如果其中一个可能的返回值中包含整数文本,则推断返回类型为 Any
问题: KT-20226
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,从 lambda 返回的整数类型对于存在提前返回的情况将更加具体
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
正确捕获具有递归类型的星号投影
问题: KT-33012
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,由于递归类型的捕获将更正确地工作,因此将有更多候选者变得适用
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
具有非 proper type(恰当类型)和 flexible one(灵活类型)的公共超类型计算导致不正确的结果
问题: KT-37054
组件: 核心语言
不兼容变更类型: 行为
简短摘要: 自 Kotlin 1.4 以来,flexible types(灵活类型)之间的公共超类型将更加具体,以防止运行时错误
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
由于缺少针对可空类型参数的捕获转换导致的类型安全问题
问题: KT-35487
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,捕获类型和可空类型之间的子类型化将更加正确,以防止运行时错误
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
在 unchecked cast(未检查类型转换)之后保留 covariant types(协变类型)的 intersection type(交集类型)
问题: KT-37280
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,covariant types(协变类型)的 uchecked cast(未检查类型转换)会为智能类型转换生成 intersection type(交集类型),而不是 unchecked cast(未检查类型转换)的类型。
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
由于使用 this 表达式,类型变量从 builder inference(构建器推断)中泄漏
问题: KT-32126
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,如果不存在其他适当的约束,则禁止在像
sequence {}
这样的构建器函数中使用this
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
具有可空类型参数的逆变类型的错误重载解析
问题: KT-31670
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,如果接受逆变类型参数的函数的两个重载仅在类型的可空性上有所不同(例如
In<T>
和In<T?>
),则认为可空类型更具体。弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
具有非嵌套递归约束的构建器推断
问题: KT-34975
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,类型依赖于传递的 lambda 内部的递归约束的构建器函数(如
sequence {}
)会导致编译器错误。弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
急切的类型变量固定导致矛盾的约束系统
问题: KT-25175
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,某些情况下的类型推断不再那么急切,从而可以找到不矛盾的约束系统。
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NewInference
暂时恢复到 1.4 之前的行为。 请注意,此标志还将禁用一些新的语言功能。
禁止在 open 函数上使用 tailrec 修饰符
问题: KT-18541
组件: 核心语言
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,函数不能同时具有
open
和tailrec
修饰符。弃用周期:
- < 1.4: 报告同时具有
open
和tailrec
修饰符的函数上的警告(在 progressive mode(渐进模式)下为错误)。- >= 1.4: 将此警告提升为错误。
伴生对象的 INSTANCE 字段比伴生对象类本身更可见
问题: KT-11567
组件: Kotlin/JVM
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,如果伴生对象是私有的,那么它的字段
INSTANCE
也将是私有的弃用周期:
- < 1.4: 编译器生成具有弃用标志的对象
INSTANCE
- >= 1.4: 伴生对象
INSTANCE
字段具有适当的可见性
在没有 finally 的内部 try 块的 catch 间隔中,不排除在 return 之前插入的外部 finally 块
问题: KT-31923
组件: Kotlin/JVM
不兼容变更类型: 行为
简短摘要: 自 Kotlin 1.4 以来,将为嵌套的
try/catch
块正确计算 catch 间隔弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-ProperFinally
暂时恢复到 1.4 之前的行为
在协变和泛型专用重写中使用内联类的 boxed 版本作为返回类型
问题: KT-30419
组件: Kotlin/JVM
不兼容变更类型: 行为
简短摘要: 自 Kotlin 1.4 以来,使用协变和泛型专用重写的函数将返回内联类的 boxed 值
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改
使用委托给 Kotlin 接口时,不要在 JVM 字节码中声明 checked exceptions(受检异常)
问题: KT-35834
组件: Kotlin/JVM
不兼容变更类型: 源码
简短摘要: Kotlin 1.4 不会在接口委托给 Kotlin 接口期间生成 checked exceptions(受检异常)
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-DoNotGenerateThrowsForDelegatedKotlinMembers
暂时恢复到 1.4 之前的行为
更改了对具有单个 vararg 参数的方法的 signature-polymorphic(签名多态)调用的行为,以避免将参数包装到另一个数组中
问题: KT-35469
组件: Kotlin/JVM
不兼容变更类型: 源码
简短摘要: Kotlin 1.4 不会将参数包装到 signature-polymorphic(签名多态)调用的另一个数组中
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改
当 KClass 用作泛型参数时,注解中的泛型签名不正确
问题: KT-35207
组件: Kotlin/JVM
不兼容变更类型: 源码
简短摘要: 当 KClass 用作泛型参数时,Kotlin 1.4 将修复注解中不正确的类型映射
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改
禁止在 signature-polymorphic(签名多态)调用中使用 spread operator(展开运算符)
问题: KT-35226
组件: Kotlin/JVM
不兼容变更类型: 源码
简短摘要: Kotlin 1.4 将禁止在 signature-polymorphic(签名多态)调用中使用 spread operator(展开运算符)(*)
弃用周期:
- < 1.4: 报告在 signature-polymorphic(签名多态)调用中使用 spread operator(展开运算符)的警告
- >= 1.5: 将此警告提升为错误, 可以使用
-XXLanguage:-ProhibitSpreadOnSignaturePolymorphicCall
暂时恢复到 1.4 之前的行为
更改 tail-recursive(尾递归)优化函数的默认值的初始化顺序
问题: KT-31540
组件: Kotlin/JVM
不兼容变更类型: 行为
简短摘要: 自 Kotlin 1.4 以来,tail-recursive(尾递归)函数的初始化顺序将与常规函数相同
弃用周期:
- < 1.4: 在有问题的函数的声明位置报告警告
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-ProperComputationOrderOfTailrecDefaultParameters
暂时恢复到 1.4 之前的行为
不要为非 const vals 生成 ConstantValue 属性
问题: KT-16615
组件: Kotlin/JVM
不兼容变更类型: 行为
简短摘要: 自 Kotlin 1.4 以来,编译器将不会为非
const
val
生成ConstantValue
属性弃用周期:
- < 1.4: 通过 IntelliJ IDEA 检查报告警告
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-NoConstantValueAttributeForNonConstVals
暂时恢复到 1.4 之前的行为
在 open 方法上为 @JvmOverloads 生成的重载应该是 final
问题: KT-33240
组件: Kotlin/JVM
不兼容变更类型: 源码
简短摘要: 具有
@JvmOverloads
的函数的重载将生成为final
弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改, 可以使用
-XXLanguage:-GenerateJvmOverloadsAsFinal
暂时恢复到 1.4 之前的行为
返回 kotlin.Result 的 Lambdas 现在返回 boxed 值而不是 unboxed 值
问题: KT-39198
组件: Kotlin/JVM
不兼容变更类型: 行为
简短摘要: 自 Kotlin 1.4 以来,返回
kotlin.Result
类型值的 lambdas 将返回 boxed 值而不是 unboxed 值弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改
统一空值检查中的异常
问题: KT-22275
组件: Kotlin/JVM
不兼容变更类型: 行为
简短摘要: 从 Kotlin 1.4 开始,所有运行时空值检查都将抛出
java.lang.NullPointerException
弃用周期:
- < 1.4: 运行时空值检查会抛出不同的异常,例如
KotlinNullPointerException
、IllegalStateException
、IllegalArgumentException
和TypeCastException
- >= 1.4: 所有运行时空值检查都抛出
java.lang.NullPointerException
。 可以使用-Xno-unified-null-checks
暂时恢复到 1.4 之前的行为
在数组/列表操作 contains、indexOf、lastIndexOf 中比较浮点值:IEEE 754 或 total order(全序)
问题: KT-28753
组件: kotlin-stdlib (JVM)
不兼容变更类型: 行为
简短摘要: 从
Double/FloatArray.asList()
返回的List
实现将实现contains
、indexOf
和lastIndexOf
,以便它们使用 total order equality(全序相等)弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改
逐步将 collection 的 min 和 max 函数的返回类型更改为 non-nullable(非空)
问题: KT-38854
组件: kotlin-stdlib (JVM)
不兼容变更类型: 源码
简短摘要: collection 的
min
和max
函数的返回类型将在 1.6 中更改为 non-nullable(非空)弃用周期:
- 1.4: 引入
...OrNull
函数作为同义词并弃用受影响的 API (参见 issue 中的详细信息)- 1.5.x: 将受影响的 API 的弃用级别提高到 error
- >=1.6: 重新引入受影响的 API,但使用 non-nullable(非空)返回类型
弃用 appendln 以支持 appendLine
问题: KT-38754
组件: kotlin-stdlib (JVM)
不兼容变更类型: 源码
简短摘要:
StringBuilder.appendln()
将被弃用以支持StringBuilder.appendLine()
弃用周期:
- 1.4: 引入
appendLine
函数作为appendln
的替代品并弃用appendln
- >=1.5: 将弃用级别提高到 error
弃用浮点类型到 Short 和 Byte 的转换
问题: KT-30360
组件: kotlin-stdlib (JVM)
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,浮点类型到
Short
和Byte
的转换将被弃用弃用周期:
- 1.4: 弃用
Double.toShort()/toByte()
和Float.toShort()/toByte()
并提出替代方案- >=1.5: 将弃用级别提高到 error
在无效的 startIndex 上快速失败 Regex.findAll
问题: KT-28356
组件: kotlin-stdlib
不兼容变更类型: 行为
简短摘要: 自 Kotlin 1.4 以来,
findAll
将得到改进,以检查startIndex
是否在输入字符序列的有效位置索引范围内,并在进入findAll
时抛出IndexOutOfBoundsException
,如果不是弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改
移除已弃用的 kotlin.coroutines.experimental
问题: KT-36083
组件: kotlin-stdlib
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,已弃用的
kotlin.coroutines.experimental
API 已从 stdlib 中移除弃用周期:
- < 1.4:
kotlin.coroutines.experimental
已被弃用,级别为ERROR
- >= 1.4:
kotlin.coroutines.experimental
已从 stdlib 中移除。 在 JVM 上,提供了一个单独的兼容性工件 (参见 issue 中的详细信息)。
移除已弃用的 mod 运算符
问题: KT-26654
组件: kotlin-stdlib
不兼容变更类型: 源码
简短摘要: 自 Kotlin 1.4 以来,numeric types(数值类型)上的
mod
运算符已从 stdlib 中移除弃用周期:
- < 1.4:
mod
已被弃用,级别为ERROR
- >= 1.4:
mod
已从 stdlib 中移除
隐藏 Throwable.addSuppressed 成员并优先使用扩展
问题: KT-38777
组件: kotlin-stdlib
不兼容变更类型: 行为
简短摘要: 现在,
Throwable.addSuppressed()
扩展函数优先于Throwable.addSuppressed()
成员函数弃用周期:
- < 1.4: 旧的行为 (参见 issue 中的详细信息)
- >= 1.4: 行为已更改
capitalize 应该将 digraphs(二合字母)转换为 title case(首字母大写)
问题: KT-38817
组件: kotlin-stdlib
不兼容变更类型: 行为
简短摘要:
String.capitalize()
函数现在以 title case(首字母大写)的形式大写 Serbo-Croatian Gaj's Latin alphabet 中的 digraphs(二合字母)(Dž
代替DŽ
)弃用周期:
- < 1.4: digraphs(二合字母)以大写形式大写 (
DŽ
)- >= 1.4: digraphs(二合字母)以 title case(首字母大写)形式大写 (
Dž
)
工具
带有分隔符的编译器参数必须在 Windows 上用双引号传递
问题: KT-41309
组件: CLI
不兼容变更类型: 行为
简短摘要: 在 Windows 上,包含分隔符(空格、
=
、;
、,
)的kotlinc.bat
参数现在需要双引号 ("
)弃用周期:
- < 1.4: 所有编译器参数都传递时不带引号
- >= 1.4: 包含分隔符(空格、
=
、;
、,
)的编译器参数需要双引号 ("
)
KAPT: 属性的合成 $annotations() 方法的名称已更改
问题: KT-36926
组件: KAPT
不兼容变更类型: 行为
**简