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


428

我想知道是否有一种方法可以检查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
    }
}

3
也许您需要的是使该属性可为空(将类型更改为File?),然后仅检查它是否为null?
MarcinKoziński16年

1
好吧,我实际上已经尝试过了,并且可以解决问题,但是我必须将allSeriesvar 编辑为seriesDir?.listFiles()?.map { it.name }?.toTypedArray(),这不是很“漂亮”
Mathew Hany

1
您可以做一个普通的旧的空检查,而智能转换将使其更漂亮。if (seriesDir != null) { allSeries = seriesDir.listFiles().map { it.name }.toTypedArray() }
MarcinKoziński16年

请考虑接受更多最新的答案
misanthrope

Answers:


977

lateinitKotlin 1.2中的一项改进允许直接检查lateinit变量的初始化状态:

lateinit var file: File    

if (this::file.isInitialized) { ... }

请参阅JetBrains博客上的公告KEEP建议

更新: Kotlin 1.2已发布。您可以在lateinit此处找到增强功能:


3
@ fer.marino:好吧,Kotlin 1.2实际上允许您lateinit也使用局部变量,请参阅kotlinlang.org/docs/reference/…–
xsveda

9
this :: lateinitVar.isInitialized
vihkat 18-10-11

17
::之前是什么意思file
默温德·辛格

5
@MalwinderSingh它创建一个成员引用或类引用。
notGeek19年

5
现在爱上了科特林
Naveed Ahmad


39

尝试使用它,UninitializedPropertyAccessException如果尚未初始化,则会收到一个。

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

编辑:基于您想要做这样的事情会更好地工作:

val chosenFile = SimpleObjectProperty<File?>
val button: Button

// Disables the button if chosenFile.get() is null
button.disableProperty.bind(chosenFile.isNull())

我有一个JavaFX应用程序,还有一个按钮,除非lateinit已初始化变量(为),否则该按钮将始终被禁用。换句话说:只要变量尚未初始化,我希望按钮被禁用。有什么好办法吗?
Mathew Hany

@MathewHany将如何正常初始化?您可能需要查看属性获取器/设置器和SimpleBooleanProperty,可以将其绑定到按钮的disabled属性
Kiskae16年

1
更具体地说,我有一个简单的应用程序,其中包含4个按钮,第一个按钮将打开DirectoryChooser对话框,而其他三个将被禁用,当用户选择目录时,所有其他按钮将对用户可用。
Mathew Hany

@MathewHany您可以使用SimpleObjectProperty来保存所选文件,然后使用isNull绑定来禁用其他按钮,从而在本地实现该功能。
Kiskae


18

您可以通过以下方式轻松实现此目的:

::variableName.isInitialized

要么

this::variableName.isInitialized

但是,如果您在侦听器或内部类中,请执行以下操作:

this@YourClassName::variableName.isInitialized

注意:如果您在声明变量的同一文件(同一类或内部类)中编写上述语句,则上述语句可以正常工作,但是如果您要检查其他类(不是超类或在其中声明)的变量,则上述语句将不起作用另一个文件),例如:

class Test {
    lateinit var str:String
}

并检查str是否已初始化:

在此处输入图片说明

我们在这里做访问场strTestTest2类。现在,我们得到了一个不可访问的错误支持字段var。检查已经对此提出的问题


12

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

lateinit var file: File

if (this::file.isInitialized) {

    // file is not null
}

使用此检查时,我使用的是本地初始化变量,该变量会给出诸如未解决的引用之类的错误
MarGin

3

要检查a是否lateinit var已初始化,请使用.isInitialized对该属性的引用:

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

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


1
::之前是什么意思bar
默温德·辛格

@Malwinder Singh“创建成员引用或类引用”
-Kotlin

0
kotlin.UninitializedPropertyAccessException: lateinit property clientKeypair has not been initialized

字节码说……等等等等。

public final static synthetic access$getClientKeypair$p(Lcom/takharsh/ecdh/MainActivity;)Ljava/security/KeyPair;

`L0
LINENUMBER 11 L0
ALOAD 0
GETFIELD com/takharsh/ecdh/MainActivity.clientKeypair : Ljava/security/KeyPair;
DUP
IFNONNULL L1
LDC "clientKeypair"
INVOKESTATIC kotlin/jvm/internal/Intrinsics.throwUninitializedPropertyAccessException (Ljava/lang/String;)V
    L1
ARETURN

L2 LOCALVARIABLE $ this Lcom / takharsh / ecdh / MainActivity; L0 L2 0 MAXSTACK = 2 MAXLOCALS = 1

Kotlin创建一个相同实例的额外局部变量,并检查它是否为null,如果为null,则抛出'throwUninitializedPropertyAccessException',否则返回本地对象。上面的字节码在这里说明 解决方法自kotlin 1.2起,它允许检查天气lateinit var是否已初始化或未使用.isInitialized

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.