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

a5g8bdjr  于 2022-12-13  发布在  Kotlin
关注(0)|答案(9)|浏览(331)

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

nhhxz33t1#

Kotlin1.2中有一个lateinit改进,允许直接检查lateinit变量的初始化状态:

lateinit var file: File    

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

请参见JetBrains blogKEEP proposal上的公告。

**更新:**Kotlin1.2已经发布。您可以在这里找到lateinit增强功能:

  • 检查是否已初始化lateinit var
  • Lateinit顶级属性和局部变量
kxeu7u2r

kxeu7u2r2#

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

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

wkftcu5l3#

您可以通过以下方式轻松完成此操作:

::variableName.isInitialized

this::variableName.isInitialized

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

this@OuterClassName::variableName.isInitialized

注意:如果您将上述语句写入声明变量的同一文件(同一类或内部类),则这些语句可以正常工作,但如果您要检查其他类(可能是超类或任何其他示例化的类)的变量,则无法正常工作,例如:

class Test {
    lateinit var str:String
}

检查str是否已初始化:

我们在这里做什么:正在检查isInitialized,以查找Test2类中Test类的str字段。我们得到一个错误,即此时var的后备字段不可访问。请检查已针对此问题引发的question

gg58donl

gg58donl4#

尝试使用它,如果它未初始化,您将收到UninitializedPropertyAccessException
lateinit专门用于在构造之后但在实际使用之前初始化字段的情况(大多数注入框架使用的模型)。如果这不是您的用例,lateinit可能不是正确的选择。
编辑:根据你想做的事情,像这样的事情会更好:

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

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

7tofc5zh5#

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

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
}
wb1gzix0

wb1gzix06#

这样就行了

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

bd1hkmkf7#

Accepted answerKotlin 1.3+中给了我一个编译器错误,我不得不在::之前显式地提到this关键字。下面是工作代码。

lateinit var file: File

if (this::file.isInitialized) {

    // file is not null
}
xe55xuns

xe55xuns8#

正在检查lateinit变量

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

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

PlaygroundKotlin的代码可能如下所示:

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

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

8iwquhpp

8iwquhpp9#

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本地可变$此Lcom/takharsh/ecdh/主要活动; L0 L2 0最大堆栈= 2最大局部= 1
Kotlin创建一个相同示例的额外的局部变量,并检查它是否为空,如果为空,则抛出'throwUninitializedPropertyAccessException',否则返回局部对象。上面的字节码解释了here解决方案从kotlin 1. 2开始,它允许检查lateinit var是否已经初始化,或者是否使用.isInitialized

相关问题