既然Kotlin是静态类型语言,为何if/else可返回不同类型赋值给变量?
Kotlin静态类型推断疑问解答
问题场景
测试Kotlin静态类型特性时遇到如下疑问:编写了一段包含if/else表达式的代码,向未显式声明类型的变量赋值,按预期如果if/else返回不同类型的值,编译器应该报错,但实际编译运行正常。
测试代码
fun main(args: Array<String>) { var a = args[0].toInt() var x = if (a < 5) { 5 } else { "hello" } println(x::class) x = 38 println(x::class) x = "test" println(x::class) x = 45.9f println(x::class) x = 32L println(x::class) }
编译执行步骤及结果
kotlin test.kt -include-runtime -d test.jar java -jar test.jar 45 class kotlin.String class kotlin.Int class kotlin.String class kotlin.Float class kotlin.Long
疑问
在静态类型语言中,这类跨类型的动态赋值不该有编译期限制吗?Kotlin编译器为什么没有阻止推断这种"模糊类型"?
原因解析
Kotlin是静态类型语言,但这里编译器并没有推断出所谓的"模糊类型",而是自动推导变量x的静态类型为Any——Kotlin的根类型,所有类(包括基本类型的装箱实现)都直接或间接继承自Any。
编译阶段x的静态类型已经确定为Any,后续给它赋值Int、String、Float等类型的值完全符合静态类型规则,因为这些类型都是Any的子类型。
你看到的运行时输出的不同类型,是变量存储的实际对象的运行时类型,这和编译期确定的静态类型并不冲突:静态类型负责编译期的类型检查,运行时类型是对象的实际类型,这在静态类型语言中是常规行为(比如Java中Object类型变量也可以存储任意对象)。
如果需要让编译器限制x的类型范围,只需显式声明变量类型即可,比如var x: Int,这时如果if/else分支返回Int和String两种类型,编译器会直接报错,因为无法将String类型赋值给Int类型变量。
内容的提问来源于stack exchange,提问作者Vinicius
相关产品推荐
相关产品推荐

