Cả hai đều dùng để khởi tạo muộn một property non-null, nhưng ai khởi tạo và khi nào thì khác nhau:
lateinit var | val ... by lazy { } | |
|---|---|---|
| Kiểu biến | var (gán lại được) | val (chỉ đọc) |
| Ai gán giá trị | Code bên ngoài gán sau (DI, onCreate, setUp của test) | Lambda tự chạy một lần ở lần đọc đầu tiên |
| Kiểu dữ liệu | Non-null, không dùng cho kiểu primitive (Int, Boolean...) | Mọi kiểu |
| Đọc trước khi có giá trị | Ném UninitializedPropertyAccessException | Không xảy ra — đọc là tự tính |
| Thread-safety | Không có sẵn | Mặc định SYNCHRONIZED |
kotlin
class ProfileFragment : Fragment() {
@Inject lateinit var analytics: Analytics // injected by Hilt later
private val dateFormatter by lazy { // built on first use only
DateTimeFormatter.ofPattern("dd/MM/yyyy")
}
}Kiểm tra đã gán chưa bằng this::analytics.isInitialized.
Lưu ý: dùng lateinit khi giá trị đến từ bên ngoài (DI, lifecycle), dùng lazy khi giá trị tính được ngay tại chỗ nhưng tốn kém. Nếu chỉ đọc trên main thread, lazy(LazyThreadSafetyMode.NONE) bỏ được chi phí lock.