为何Kotlin允许非空值声明为可空类型却仍按非空处理?
Kotlin中为何允许将非空Map的值声明为可空类型后直接传给非空参数?
先看你给出的代码:
class WorkoutHistory( history: Map<Workout, Int> = EnumMap(Workout::class.java) ) { private val history: EnumMap<Workout, Int> = EnumMap(history) init { history.forEach { (workout: Workout, reps: Int?) -> doSomething(workout, reps) } } private fun doSomething(workout: Workout, reps: Int) { // Do something } }
这是Kotlin编译器的有意设计,并非疏漏,原因可以拆解为两点:
参数类型的向上兼容:
Map<Workout, Int>的forEach方法接收的lambda参数类型是(Workout, Int) -> Unit,但Kotlin允许你给lambda里的参数声明更宽泛的类型(这里把Int声明为Int?)。因为非空类型Int是可空类型Int?的子类型,这种向上转型是完全安全的,编译器不会阻止你这么做。智能类型推断的作用:虽然你把
reps声明成了Int?,但编译器能通过上下文判断出实际值的非空性——原始的history是EnumMap<Workout, Int>,其中存储的所有值都是非空的Int,所以遍历出来的reps不可能为null。基于这个推断,编译器允许你直接把reps传给要求非空Int参数的doSomething函数,不会触发空安全检查报错。
你可以做个测试:如果把构造函数的history参数改成Map<Workout, Int?>,这时候编译器就会立刻报错,提示你reps可能为null,必须做非空处理(比如用reps!!或者reps?.let{...})。
内容的提问来源于stack exchange,提问作者fraterboots
相关产品推荐
相关产品推荐

