如何检查“lateinit”变量是不是已初始化?
Posted
技术标签:
【中文标题】如何检查“lateinit”变量是不是已初始化?【英文标题】:How to check if a "lateinit" variable has been initialized?如何检查“lateinit”变量是否已初始化? 【发布时间】:2016-10-03 18:39:32 【问题描述】:我想知道是否有办法检查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
【问题讨论】:
也许您需要使属性为空(将类型更改为File?
),然后检查它是否为空?
好吧,我确实试过了,它会成功,但是我必须将allSeries
var 编辑为seriesDir?.listFiles()?.map it.name ?.toTypedArray()
,这不是很“漂亮”
你可以做一个普通的旧空检查,智能转换会让它更漂亮。 if (seriesDir != null)
allSeries = seriesDir.listFiles().map it.name .toTypedArray()
请考虑接受更多最新的answer
【参考方案1】:
这会起作用
if (::list.isInitialized)
//true
else
//false
【讨论】:
【参考方案2】:对我来说有效
if (::file.isInitialized)
//true
else
//false
【讨论】:
【参考方案3】:使用.isInitialized
属性可以检查lateinit 变量的初始化状态。
if (::file.isInitialized)
// File is initialized
else
// File is not initialized
【讨论】:
这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review @gforce301 它将明确用于检查。 嗯,这是在具有 Kotlin 版本 1.3 的 android Studio 上对我有用的唯一答案 @gforce301 为什么这不能回答问题?原来的问题变了吗?现在好像可以回答了……【参考方案4】:如果你在一个类中有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
【讨论】:
您需要添加一个函数来检查是否已初始化,这有点荒谬。【参考方案5】:您可以通过以下方式轻松做到这一点:
::variableName.isInitialized
或
this::variableName.isInitialized
但是,如果您在侦听器或内部类中,请执行以下操作:
this@OuterClassName::variableName.isInitialized
注意:如果您将上述语句写在声明变量的同一个文件(同一类或内部类)中,则上述语句可以正常工作,但如果您想检查其他类的变量,这将不起作用(可以是超类或任何其他实例化的类),例如:
class Test
lateinit var str:String
并检查 str 是否已初始化:
我们在这里做什么:检查isInitialized
字段str
的Test
类在Test2
类中。
我们得到一个错误,此时无法访问 var 的支持字段。
检查已经提出的question。
【讨论】:
正是我正在寻找的东西,并直接将我指向正确的方向 这应该是详细程度的公认答案:)【参考方案6】:Kotlin 1.2 中有一个lateinit
改进,允许直接检查lateinit
变量的初始化状态:
lateinit var file: File
if (this::file.isInitialized) ...
请参阅JetBrains blog 或KEEP proposal 上的公告。
更新: Kotlin 1.2 已经发布。您可以在此处找到lateinit
增强功能:
【讨论】:
@fer.marino:嗯,Kotlin 1.2 实际上允许您将lateinit
也用于局部变量,请参阅kotlinlang.org/docs/reference/…
this::lateinitVar.isInitialized
::
前面的file
是什么意思?
@MalwinderSingh 它创建一个成员引用或一个类引用。
我们如何检查本地lateinit
,其中this
是不同的东西?【参考方案7】:
Accepted answer 在Kotlin 1.3+
中给我一个编译器错误,我必须在::
之前明确提及this
关键字。下面是工作代码。
lateinit var file: File
if (this::file.isInitialized)
// file is not null
【讨论】:
当我使用这个检查时,我使用了一个本地初始化变量,它给出了一个错误,比如未解析的引用【参考方案8】: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 开始,它允许使用 .isInitialized
来检查天气 lateinit var 是否已初始化。
【讨论】:
【参考方案9】:尝试使用它,如果未初始化,您将收到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
)已被初始化,否则该按钮将始终处于禁用状态。换句话说:只要变量尚未初始化,我希望按钮被禁用。有什么好的方法吗?
@MathewHany 如何正常初始化?您可能想查看属性 getter/setter 和 SimpleBooleanProperty,您可以将其绑定到按钮的 disabled 属性
更具体地说,我有一个包含 4 个按钮的简单应用程序,第一个按钮将打开一个 DirectoryChooser 对话框,其他 3 个按钮将被禁用,当用户选择目录时,所有其他按钮按钮将可供用户使用。
@MathewHany 您可以使用 SimpleObjectProperty 来保存所选文件,然后使用 isNull
绑定来禁用其他按钮。
kotlinlang.org/docs/reference/… xsveda 答案是最新的【参考方案10】:
要检查 lateinit var
是否已初始化或未在对该属性的引用上使用 .isInitialized
:
if (foo::bar.isInitialized)
println(foo.bar)
此检查仅适用于可通过词法访问的属性,即以相同类型或外部类型之一声明,或在同一文件的顶层声明。
【讨论】:
::
前面的bar
是什么意思?
@Malwinder Singh “创建成员引用或类引用” - Kotlin Doc以上是关于如何检查“lateinit”变量是不是已初始化?的主要内容,如果未能解决你的问题,请参考以下文章
Android开发Kotlin检查lateinit变量是否已初始化的方法
为啥我得到 kotlin.UninitializedPropertyAccessException 即使 lateinit 属性已初始化(可能)
Kotlin类的初始化 ④ ( lateinit 延迟初始化 | ::属性名称.isInitialized 检查属性是否初始化 | lazy 惰性初始化 )
Kotlin类的初始化 ④ ( lateinit 延迟初始化 | ::属性名称.isInitialized 检查属性是否初始化 | lazy 惰性初始化 )