如何检查" lateinit"变量已初始化?

时间:2016-06-03 15:53:57

标签: kotlin

我想知道是否有办法检查lateinit变量是否已初始化。

import javafx.application.Application
import javafx.event.EventHandler
import javafx.geometry.Insets
import javafx.geometry.Pos
import javafx.scene.Scene
import javafx.scene.control.Button
import javafx.scene.control.ComboBox
import javafx.scene.layout.VBox
import javafx.stage.DirectoryChooser
import javafx.stage.Stage
import java.io.File

class SeriesManager() {
    lateinit var seriesDir: File
    val allSeries by lazy {
        seriesDir.listFiles().map { it.name }.toTypedArray()
    }
}

class SeriesManagerUI : Application() {
    override fun start(primaryStage: Stage) {
        val sm = SeriesManager()

        val setSeriesDirBtn = Button("Change all series location").apply {
            onAction = EventHandler {
                sm.seriesDir = DirectoryChooser().apply {
                    title = "Choose all series location"
                }.showDialog(primaryStage)
            }
        }
        val allSeriesList = ComboBox<String>().apply {
            promptText = "Select a series from here"
            isDisable = // I want this to be always true, unless the SeriesManager.seriesDir has been initialized
        }
        val setCurrentEpisodeBtn = Button("Change the current episode")
        val openNextEpisode = Button("Watch the next episode")

        val layout = VBox(
            setSeriesDirBtn,
            allSeriesList,
            setCurrentEpisodeBtn,
            openNextEpisode
        ).apply {
            padding = Insets(15.0)
            spacing = 10.0
            alignment = Pos.CENTER
        }

        primaryStage.apply {
            scene = Scene(layout).apply {
                minWidth = 300.0
                isResizable = false
            }

            title = "Series Manager"
        }.show()
    }
}

fun main(args: Array<String>) {
    Application.launch(SeriesManagerUI::class.java, *args)
}

9 个答案:

答案 0 :(得分:611)

Kotlin 1.2中有lateinit个改进,允许直接检查lateinit变量的初始化状态:

lateinit var file: File    

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

查看JetBrains blogKEEP proposal上的公告。

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

答案 1 :(得分:38)

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

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

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

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

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

答案 2 :(得分:36)

您可以通过以下方式轻松地做到这一点:

::variableName.isInitialized

this::variableName.isInitialized

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

this@YourClassName::variableName.isInitialized

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

class Test {
    lateinit var str:String
}

并检查str是否已初始化:

enter image description here

我们在这里做什么:检查isInitialized类中str类的字段Test的{​​{1}}。 现在,我们得到了一个不可访问的错误支持字段var。 检查已经对此提出的question

答案 3 :(得分:18)

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

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

答案 4 :(得分:7)

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

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

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

示例:

class Foo() {

    private lateinit var myFile: File

    fun isFileInitialised() = ::file.isInitialized
}

 // in another class
class Bar() {

    val foo = Foo()

    if(foo.isFileInitialised()) // this should work
}

答案 5 :(得分:3)

对我来说有效

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

答案 6 :(得分:0)

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

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

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

答案 7 :(得分:0)

Accepted answer给了我Kotlin 1.3+一个编译器错误,我不得不在this之前明确提到::关键字。下面是工作代码。

lateinit var file: File

if (this::file.isInitialized) {

    // file is not null
}

答案 8 :(得分: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     本地$ this Lcom / takharsh / ecdh / MainActivity; L0 L2 0     最大堆栈= 2     MAXLOCALS = 1

Kotlin创建一个相同实例的额外本地变量,并检查它是否为null,如果为null,则抛出'throwUninitializedPropertyAccessException',否则返回本地对象。 上面的字节码说明了here 解 从kotlin 1.2开始,它允许检查天气Lateinit var是否已使用.isInitialized

初始化