Di Kotlin jika Anda tidak ingin menginisialisasi properti kelas di dalam konstruktor atau di bagian atas badan kelas, Anda pada dasarnya memiliki dua opsi ini (dari referensi bahasa):
lazy () adalah fungsi yang mengambil lambda dan mengembalikan instance Malas yang dapat berfungsi sebagai delegasi untuk mengimplementasikan properti lazy: panggilan pertama untuk mendapatkan () mengeksekusi lambda yang dilewatkan ke lazy () dan mengingat hasilnya, panggilan selanjutnya untuk mendapatkan () cukup kembalikan hasil yang diingat.
Contoh
public class Hello { val myLazyString: String by lazy { "Hello" } }
Jadi panggilan pertama dan panggilan subquential, di mana pun itu, ke myLazyString akan mengembalikan "Halo"
Biasanya, properti yang dideklarasikan memiliki tipe non-null harus diinisialisasi dalam konstruktor. Namun, cukup sering ini tidak nyaman. Misalnya, properti dapat diinisialisasi melalui injeksi dependensi, atau dalam metode pengaturan tes unit. Dalam hal ini, Anda tidak bisa menyediakan inisialisasi non-null di konstruktor, tetapi Anda masih ingin menghindari cek nol ketika mereferensikan properti di dalam tubuh kelas.
Untuk menangani kasus ini, Anda dapat menandai properti dengan pengubah lateinit:
public class MyTest { lateinit var subject: TestSubject @SetUp fun setup() { subject = TestSubject() } @Test fun test() { subject.method() } }
Pengubah hanya dapat digunakan pada properti var dideklarasikan di dalam tubuh kelas (tidak di konstruktor utama), dan hanya ketika properti tidak memiliki pengambil atau penyetel kustom. Jenis properti harus bukan nol, dan tidak boleh tipe primitif.
Jadi, bagaimana memilih dengan benar antara kedua opsi ini, karena keduanya dapat menyelesaikan masalah yang sama?
sumber
lateinit
memperlihatkan bidang dukungan dengan visibilitas setter sehingga cara properti diakses dari Kotlin dan dari Jawa berbeda. Dan dari kode Java properti ini dapat disetel menjadinull
tanpa cek di Kotlin. Karenalateinit
itu bukan untuk inisialisasi malas tetapi untuk inisialisasi tidak harus dari kode Kotlin.Lazy
+ yang disimpan secara eksplisit.isInitialized()
untuk melakukan itu. Saya kira tidak ada cara langsung untuk memeriksa properti seperti itunull
karena jaminan yang tidak dapat Anda perolehnull
dari properti itu. :) Lihat demo ini .by lazy
dapat memperlambat waktu pembuatan atau runtime?lateinit
untuk menghindari penggunaannull
untuk nilai yang tidak diinisialisasi. Selain itunull
jangan pernah digunakan, dan denganlateinit
nol dapat dihilangkan. Begitulah cara saya mencintai Kotlin :)Selain
hotkey
jawaban yang bagus, berikut adalah cara saya memilih di antara keduanya dalam praktik:lateinit
adalah untuk inisialisasi eksternal: ketika Anda membutuhkan hal-hal eksternal untuk menginisialisasi nilai Anda dengan memanggil metode.misalnya dengan menelepon:
Sedangkan
lazy
saat itu hanya menggunakan dependensi internal untuk objek Anda.sumber
Jawaban yang sangat singkat dan ringkas
lateinit: Ini menginisialisasi properti non-null belakangan ini
Tidak seperti inisialisasi malas, lateinit memungkinkan kompiler untuk mengenali bahwa nilai properti non-null tidak disimpan dalam tahap konstruktor untuk dikompilasi secara normal.
Inisialisasi malas
oleh lazy mungkin sangat berguna ketika mengimplementasikan properti read-only (val) yang melakukan inisialisasi lazy di Kotlin.
oleh lazy {...} melakukan inisialisasi di mana properti yang didefinisikan pertama kali digunakan, bukan deklarasi.
sumber
lateinit vs malas
keterlambatan
i) Gunakan dengan variabel yang bisa berubah [var]
ii) Diizinkan dengan hanya tipe data yang tidak dapat dibatalkan
iii) Ini adalah janji untuk mengkompilasi bahwa nilai akan diinisialisasi di masa depan.
CATATAN : Jika Anda mencoba mengakses variabel lateinit tanpa menginisialisasi, maka ia melempar UnInitializedPropertyAccessException.
malas
i) Inisialisasi malas dirancang untuk mencegah inisialisasi objek yang tidak perlu.
ii) Variabel Anda tidak akan diinisialisasi kecuali Anda menggunakannya.
iii) Ini diinisialisasi hanya sekali. Lain kali saat Anda menggunakannya, Anda mendapatkan nilai dari memori cache.
iv) Ini adalah thread aman (Ini diinisialisasi dalam utas di mana ia digunakan untuk pertama kalinya. Thread lain menggunakan nilai yang sama yang disimpan dalam cache).
v) Variabel hanya dapat berupa val .
vi) Variabel hanya bisa non- nullable .
sumber
Selain semua jawaban hebat, ada konsep yang disebut pemuatan malas:
Dengan menggunakannya dengan benar, Anda dapat mengurangi waktu pemuatan aplikasi Anda. Dan cara implementasi Kotlin adalah dengan
lazy()
mana memuat nilai yang dibutuhkan ke variabel Anda setiap kali dibutuhkan.Tetapi lateinit digunakan ketika Anda yakin suatu variabel tidak akan nol atau kosong dan akan diinisialisasi sebelum Anda menggunakannya -menggunakan
onResume()
metode untuk android- dan jadi Anda tidak ingin mendeklarasikannya sebagai tipe nullable.sumber
onCreateView
,onResume
dan lainnya denganlateinit
, tetapi kadang-kadang kesalahan terjadi di sana (karena beberapa peristiwa dimulai sebelumnya). Jadi mungkinby lazy
bisa memberikan hasil yang sesuai. Saya menggunakanlateinit
untuk variabel non-nol yang dapat berubah selama siklus hidup.Semuanya benar di atas, tetapi salah satu fakta penjelasan sederhana LAZY ---- Ada beberapa kasus ketika Anda ingin menunda pembuatan instance objek Anda hingga penggunaan pertama. Teknik ini dikenal sebagai inisialisasi malas atau malas instantiation. Tujuan utama inisialisasi malas adalah untuk meningkatkan kinerja dan mengurangi jejak memori Anda. Jika instantiasi instance dari jenis Anda membawa biaya komputasi yang besar dan program mungkin berakhir tidak benar-benar menggunakannya, Anda ingin menunda atau bahkan menghindari pemborosan siklus CPU.
sumber
Jika Anda menggunakan wadah Musim Semi dan Anda ingin menginisialisasi bidang kacang yang tidak dapat dibatalkan,
lateinit
lebih cocok.sumber
@Autowired lateinit var myBean: MyBean
Jika Anda menggunakan variabel yang tidak berubah, maka lebih baik menginisialisasi dengan
by lazy { ... }
atauval
. Dalam hal ini Anda dapat yakin bahwa itu akan selalu diinisialisasi ketika dibutuhkan dan paling banyak 1 kali.Jika Anda menginginkan variabel non-null, yang dapat mengubah nilainya, gunakan
lateinit var
. Dalam pengembangan Android nanti dapat menginisialisasi dalam acara-acara seperti sepertionCreate
,onResume
. Perlu diketahui, bahwa jika Anda memanggil permintaan REST dan mengakses variabel ini, itu dapat menyebabkan pengecualianUninitializedPropertyAccessException: lateinit property yourVariable has not been initialized
, karena permintaan dapat mengeksekusi lebih cepat dari yang dapat diinisialisasi variabel itu.sumber