我想知道是否有办法检查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)
}
答案 0 :(得分:611)
Kotlin 1.2中有lateinit
个改进,允许直接检查lateinit
变量的初始化状态:
lateinit var file: File
if (::file.isInitialized) { ... }
查看JetBrains blog或KEEP 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是否已初始化:
我们在这里做什么:检查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