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

Mat*_*any 322 kotlin

我想知道是否有办法检查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
    }
}
Run Code Online (Sandbox Code Playgroud)

xsv*_*eda 768

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

lateinit var file: File    

if (::file.isInitialized) { ... }
Run Code Online (Sandbox Code Playgroud)

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

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

  • 这:: lateinitVar.isInitialized (5认同)
  • `file`之前的`::`是什么意思? (5认同)
  • @ fer.marino:嗯,Kotlin 1.2实际上允许你对局部变量使用`lateinit`,参见http://kotlinlang.org/docs/reference/whatsnew12.html#lateinit-top-level-properties-and-local - 变量 (3认同)
  • @MalwinderSingh它创建一个成员引用或类引用。 (2认同)
  • 我们如何检查本地 `lateinit` 的 this,其中 `this` 是不同的? (2认同)

Sur*_*nav 53

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

::variableName.isInitialized
Run Code Online (Sandbox Code Playgroud)

或者

this::variableName.isInitialized
Run Code Online (Sandbox Code Playgroud)

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

this@OuterClassName::variableName.isInitialized
Run Code Online (Sandbox Code Playgroud)

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

class Test {
    lateinit var str:String
}
Run Code Online (Sandbox Code Playgroud)

并检查 str 是否已初始化:

在此处输入图片说明

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


Kis*_*kae 39

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

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

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

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

// Disables the button if chosenFile.get() is null
button.disableProperty.bind(chosenFile.isNull())
Run Code Online (Sandbox Code Playgroud)


Nik*_*aye 25

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

if(::file.isInitialized){
    //File is initialized
}else{
    //File is not initialized
}
Run Code Online (Sandbox Code Playgroud)

  • @ gforce301它将明确地用于检查。 (2认同)
  • 嗯,这是在具有 Kotlin 版本 1.3 的 Android Studio 上对我有用的唯一答案 (2认同)
  • @gforce301 为什么这不能回答问题?原来的问题变了吗?现在好像可以回答了... (2认同)

ARG*_*Geo 20

检查 Lateinit var

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

if (foo::bar.isInitialized) {
    println(foo.bar)
}
Run Code Online (Sandbox Code Playgroud)

Kotlin Playground 的代码可能如下所示:

fun main() {        
    var declarative = Declarative()
    declarative.checkLateInit()
}

class Declarative {   
    lateinit var compose: String

    fun checkLateInit() {            
        println(this::compose.isInitialized)
        compose = "Jetpack Compose 1.4"
      
        if (this::compose.isInitialized) {
            println(this.compose)
        }
    }
}

// Result:

// false
// Jetpack Compose 1.4
Run Code Online (Sandbox Code Playgroud)

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

  • “bar”之前的“::”是什么意思? (5认同)
  • @Malwinder Singh“创建成员引用或类引用” - Kotlin Doc (4认同)

Max*_*Max 11

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

if(foo::file.isInitialized) // this wouldn't work
Run Code Online (Sandbox Code Playgroud)

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

例子:

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
}
Run Code Online (Sandbox Code Playgroud)


Saz*_*han 6

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

lateinit var file: File

if (this::file.isInitialized) {

    // file is not null
}
Run Code Online (Sandbox Code Playgroud)