Initialization 为什么';t Kotlin是否允许将lateinit与基元类型一起使用?
在Kotlin语言中,默认情况下,我们必须在引入每个变量时对其进行初始化。为了避免这种情况,可以使用Initialization 为什么';t Kotlin是否允许将lateinit与基元类型一起使用?,initialization,kotlin,primitive,Initialization,Kotlin,Primitive,在Kotlin语言中,默认情况下,我们必须在引入每个变量时对其进行初始化。为了避免这种情况,可以使用lateinit关键字。在初始化lateinit变量之前引用该变量会导致运行时异常 然而,lateinit不能与基元类型一起使用。为什么会这样?一个简短的答案是,对于原语,您可以始终使用0作为默认值,对于可空类型null作为默认值。只有不可为空的非基元类型可能需要lateinit才能绕过类型安全系统 实际上,不需要在Kotlin中初始化变量,只要它在第一次访问之前有一个值,并且可以静态地证明它。这
lateinit
关键字。在初始化lateinit
变量之前引用该变量会导致运行时异常
然而,
lateinit
不能与基元类型一起使用。为什么会这样?一个简短的答案是,对于原语,您可以始终使用0
作为默认值,对于可空类型null
作为默认值。只有不可为空的非基元类型可能需要lateinit
才能绕过类型安全系统
实际上,不需要在Kotlin中初始化变量,只要它在第一次访问之前有一个值,并且可以静态地证明它。这意味着此代码完全有效:
fun main(args: Array<String>) {
var x: Int
val y: Double
x = 0
y = x + 0.1
println("$x, $y")
}
对于(不可为null的)对象类型,Kotlin使用null
值来标记lateinit
属性尚未初始化,并在访问该属性时引发相应的异常
对于基元类型,没有这样的值,因此无法将属性标记为未初始化,也无法提供lateinit
需要提供的诊断。(我们可以尝试使用某种单独的标记,但在通过反射初始化字段时,该标记不会更新,这是lateinit
的一个主要用例)
因此,
lateinit
仅支持对象类型的属性。我认为,对于原语,只需初始化它,让我说0并在内存中保存简单值,而不需要存储有关lateinit机制使用的对象可空性的额外信息,所需的资源就更少了
如果不是这样,请纠正我。你能在回答中澄清一下,为什么
lateinit Int
不能在运行时用Integer
类型表示,它能够在未初始化时保持null
值?因此,我认为Kotlin将基本类型包装为object(例如Int到Int)。然而,为什么Int不能保持null,因为它是一个对象?另外,为什么我们不能声明一个参数为null,并将其延迟初始化?(var x:Int?)@Yao的原因与yole解释的相同。基本上,您需要一个未使用的值,该值可用于标记var未初始化的事实。如前所述,原语没有这样的值(原语变量可以保存的所有值都是有效的)。可为null的变量也存在同样的问题:包括null在内的所有值都是有效的(您可以使用null初始化可为null的变量)。因此,没有剩余的未使用值将变量标记为未初始化。@GustavoMaciel但如果我说lateinit var int:int?
,那么我不明白为什么这不起作用,因为Kotlin已经用Integer
表示int?
。@forresthopkinsa,因为lateinit
和?
是冲突的。前者说你有一个变量在初始化后总是有一些值,后者说你有一个变量可能有一些值,也可能没有。您不需要?。
或检查lateinit
变量的空值。我认为这有点误导。它表明,需要lateinit的唯一原因是,当编译器不够聪明,无法确定属性是否已初始化时,向编译器提供提示。另一个完全有效的用例(对原语特别有用)是,如果客户机代码试图在初始化/计算某个值之前访问该值,则确保急切地抛出描述性异常,而不是基于默认值0或false默默地执行错误操作。
class Window {
@Inject lateinit parent: Parent
}