Bagaimana cara memeriksa apakah variabel "lateinit" telah diinisialisasi?

428

Saya bertanya-tanya apakah ada cara untuk memeriksa apakah suatu lateinitvariabel telah diinisialisasi. Sebagai contoh:

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
    }
}
Mathew Hany
sumber
3
Mungkin yang Anda butuhkan adalah membuat properti itu nullable (ubah tipe menjadi File?) dan periksa apakah itu null?
Marcin Koziński
1
Yah, saya benar-benar mencobanya dan itu akan melakukan trik, namun saya harus mengedit allSeriesvar seriesDir?.listFiles()?.map { it.name }?.toTypedArray(), yang tidak terlalu "cantik"
Mathew Hany
1
Anda dapat melakukan cek kosong lama yang biasa dan pemain cerdas akan membuatnya lebih cantik. if (seriesDir != null) { allSeries = seriesDir.listFiles().map { it.name }.toTypedArray() }
Marcin Koziński
Silakan pertimbangkan menerima lebih banyak jawaban
misanthrope

Jawaban:

978

Ada lateinitpeningkatan di Kotlin 1.2 yang memungkinkan untuk memeriksa status inisialisasi lateinitvariabel secara langsung:

lateinit var file: File    

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

Lihat pengumuman di blog JetBrains atau proposal KEEP .

UPDATE: Kotlin 1.2 telah dirilis. Anda dapat menemukan lateinitpeningkatan di sini:

xsveda
sumber
3
@ fer.marino: Ya, Kotlin 1.2 sebenarnya memungkinkan Anda untuk menggunakan lateinitjuga untuk variabel lokal, lihat kotlinlang.org/docs/reference/…
xsveda
9
this :: lateinitVar.isInitialized
vihkat
17
apa arti dari ::sebelumnya file?
Malwinder Singh
5
@MalwinderSingh menciptakan referensi anggota atau referensi kelas.
notGeek
5
Jatuh cinta dengan kotlin sekarang
Naveed Ahmad
46

Menggunakan .isInitializedproperti, seseorang dapat memeriksa status inisialisasi dari variabel lateinit.

if(::file.isInitialized){
    //File is initialized
}else{
    //File is not initialized
}
Nikhil Katekhaye
sumber
Ini tidak memberikan jawaban untuk pertanyaan itu. Untuk mengkritik atau meminta klarifikasi dari penulis, tinggalkan komentar di bawah posting mereka. - Dari Ulasan
gforce301
2
@ gforce301 Ini pasti akan digunakan untuk memeriksa.
Nikhil Katekhaye
39

Cobalah untuk menggunakannya dan Anda akan menerima UninitializedPropertyAccessExceptionjika itu tidak diinisialisasi.

lateinitkhusus untuk kasus di mana bidang diinisialisasi setelah konstruksi, tetapi sebelum penggunaan aktual (model yang menggunakan kerangka kerja injeksi paling banyak). Jika ini bukan use case Anda lateinitmungkin bukan pilihan yang tepat.

EDIT: Berdasarkan apa yang ingin Anda lakukan seperti ini akan bekerja lebih baik:

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

// Disables the button if chosenFile.get() is null
button.disableProperty.bind(chosenFile.isNull())
Kiskae
sumber
Saya memiliki aplikasi JavaFX, dan saya memiliki tombol yang akan selalu dinonaktifkan kecuali variabel (yang lateinit) telah diinisialisasi. Dengan kata lain: Saya ingin tombol dinonaktifkan selama variabel belum diinisialisasi. Apakah ada cara yang baik untuk melakukan itu?
Mathew Hany
@MathewHany Bagaimana cara diinisialisasi secara normal? Anda mungkin ingin melihat properti pengambil / setter dan SimpleBooleanProperty yang dapat Anda ikat ke properti yang dinonaktifkan tombol
Kiskae
1
Untuk lebih spesifik, saya memiliki aplikasi sederhana yang berisi 4 tombol, tombol pertama akan membuka dialog DirectoryChooser, dan 3 lainnya akan dinonaktifkan, ketika pengguna memilih direktori maka semua tombol lain akan tersedia untuk pengguna.
Mathew Hany
@MathewHany Anda dapat mengimplementasikannya menggunakan SimpleObjectProperty untuk menyimpan file yang dipilih, kemudian menggunakan isNullpenjilidan untuk menonaktifkan tombol lainnya.
Kiskae
1
kotlinlang.org/docs/reference/… xsveda answer lebih mutakhir
Serge
19

Anda dapat dengan mudah melakukan ini dengan:

::variableName.isInitialized

atau

this::variableName.isInitialized

Tetapi jika Anda berada di dalam pendengar atau kelas dalam, lakukan ini:

this@YourClassName::variableName.isInitialized

Catatan: Pernyataan di atas berfungsi dengan baik jika Anda menulisnya di file yang sama (kelas yang sama atau kelas dalam) di mana variabel dideklarasikan tetapi ini tidak akan berfungsi jika Anda ingin memeriksa variabel kelas lain (bukan superclass atau dideklarasikan dalam file lain) , misalnya:

class Test {
    lateinit var str:String
}

Dan untuk memeriksa apakah str diinisialisasi:

masukkan deskripsi gambar di sini

Apa yang kita lakukan di sini mengakses bidang strdari Testkelas di Test2kelas. Dan kami mendapatkan bidang dukungan kesalahan var tidak dapat diakses pada saat ini. Periksa pertanyaan yang sudah diajukan tentang ini.

Suraj Vaishnav
sumber
12

Jawaban yang diterima memberi saya kesalahan kompilator Kotlin 1.3+, saya harus menyebutkan thiskata kunci sebelumnya secara eksplisit ::. Di bawah ini adalah kode yang berfungsi.

lateinit var file: File

if (this::file.isInitialized) {

    // file is not null
}
Sazzad Hissain Khan
sumber
Saya menggunakan variabel init lokal ketika saya menggunakan cek ini yang memberikan kesalahan seperti referensi yang belum terselesaikan
MarGin
3

Untuk memeriksa apakah a lateinit vardiinisialisasi atau tidak digunakan .isInitializedpada referensi ke properti itu:

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

Pemeriksaan ini hanya tersedia untuk properti yang dapat diakses secara leksikal, yaitu dideklarasikan dalam tipe yang sama atau di salah satu tipe luar, atau pada level teratas dalam file yang sama.

Andy
sumber
1
apa arti dari ::sebelumnya bar?
Malwinder Singh
@Malwinder Singh "membuat referensi anggota atau referensi kelas" - Kotlin Doc
DMonkey
0
kotlin.UninitializedPropertyAccessException: lateinit property clientKeypair has not been initialized

Bytecode mengatakan ... bla bla ..

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 LOCALVARIABLE $ Lcom ini / takharsh / ecdh / MainActivity; L0 L2 0 MAXSTACK = 2 MAXLOCALS = 1

Kotlin membuat variabel lokal ekstra dari instance yang sama dan memeriksa apakah itu null atau tidak, jika nol lalu melempar 'throwUninitializedPropertyAccessException' yang lain mengembalikan objek lokal. Bytecode di atas dijelaskan di sini Solusi Karena kotlin 1.2 memungkinkan untuk memeriksa cuaca lateinit var telah diinisialisasi atau tidak menggunakan.isInitialized

takharsh
sumber