如何检查“lateinit”变量是否已初始化?

我想知道是否有一种方法可以检查lateinit变量是否已初始化。例如:

class Foo() {
private lateinit var myFile: File
fun bar(path: String?) {path?.let { myFile = File(it) }}
fun bar2() {myFile.whateverMethod()// May crash since I don't know whether myFile has been initialized}}
297064 次浏览

尝试使用它,如果未初始化,您将收到UninitializedPropertyAccessException

lateinit专门用于字段在构造之后但在实际使用之前初始化的情况(大多数注入框架使用的模型)。如果这不是你的用例lateinit可能不是正确的选择。

编辑:根据你想做的事情,这样做会更好:

val chosenFile = SimpleObjectProperty<File?>val button: Button
// Disables the button if chosenFile.get() is nullbutton.disableProperty.bind(chosenFile.isNull())

静态编程语言1.2中有一个lateinit改进,允许直接检查lateinit变量的初始化状态:

lateinit var file: File
if (this::file.isInitialized) { ... }

请参阅JetBrains博客KEEP提案上的公告。

更新:静态编程语言1.2已经发布。您可以在此处找到lateinit增强:

使用.isInitialized属性可以检查lateinit变量的初始化状态。

if (::file.isInitialized) {// File is initialized} else {// File is not initialized}

要检查lateinit var是否被初始化,只需在属性引用::上使用.isInitialized布尔值。

if (foo::bar.isInitialized) {println(foo.bar)}

Playground静态编程语言的代码可能如下所示:

fun main() {var declarative = Declarative()declarative.checkLateInit()}
class Declarative {lateinit var compose: String
fun checkLateInit() {println(this::compose.isInitialized)compose = "Jetpack Compose 1.2"      
if (this::compose.isInitialized) {println(this.compose)}}}
// Result:
// false// Jetpack Compose 1.2

此检查仅适用于词法可访问的属性,即以相同类型或外部类型之一声明,或在同一文件的顶层声明。

接受的答案Kotlin 1.3+中给我一个编译器错误,我必须在::之前明确提到this关键字。下面是工作代码。

lateinit var file: File
if (this::file.isInitialized) {
// file is not null}
kotlin.UninitializedPropertyAccessException: lateinit property clientKeypair has not been initialized

字节码说… blah blah…

public final static synthetic access$getClientKeypair$p(Lcom/takharsh/ecdh/MainActivity;)Ljava/security/KeyPair;
`L0LINENUMBER 11 L0ALOAD 0GETFIELD com/takharsh/ecdh/MainActivity.clientKeypair : Ljava/security/KeyPair;DUPIFNONNULL L1LDC "clientKeypair"INVOKESTATIC kotlin/jvm/internal/Intrinsics.throwUninitializedPropertyAccessException (Ljava/lang/String;)VL1ARETURN

L2LOCALVARIABLE$this Lcom/tak的/ecdh/MainActive; L0 L2 0MAXSTACK=2MAXLOCALS=1

静态编程语言为同一个实例创建一个额外的局部变量,并检查它是否为null,如果为null,则抛出'throwUn初始化属性异常',否则返回本地对象。以上字节码解释这里解决方案从kotlin 1.2开始,它允许检查天气lateinit var已初始化或未使用.isInitialized

你可以很容易地做到这一点:

::variableName.isInitialized

this::variableName.isInitialized

但是,如果您在侦听器或内部类中,请这样做:

this@OuterClassName::variableName.isInitialized

注意:如果您将它们写入声明变量的同一个文件(同一个类或内部类)中,上述语句可以正常工作,但这将不起作用如果你想检查其他类的变量(可以是超类或任何其他实例化的类),例如:

class Test {lateinit var str:String}

并检查str是否初始化:

在此处输入图片描述

我们在这里做什么:在Test2类中为Test类的字段str检查isInitialized。我们得到一个错误的支持字段,此时无法访问var。检查一个问题已经提出了这个问题。

如果一个类中有一个lateinit属性,并且需要检查它是否从另一个类初始化

if(foo::file.isInitialized) // this wouldn't work

我找到的解决方法是创建一个函数来检查属性是否已初始化,然后您可以从任何其他类调用该函数。

示例:

class Foo() {
private lateinit var myFile: File
fun isFileInitialised() = ::file.isInitialized}
// in another classclass Bar() {
val foo = Foo()
if(foo.isFileInitialised()) // this should work}

这会管用的

if (::list.isInitialized) {//true}else {//false}