오늘은 Kotlin의 lateinit var에 대해서 이해해 보겠습니다.
1. lateinit var vs by lazy
먼저, lateinit var와 by lazy를 표로 비교해 보겠습니다.
가변적이면서도 초기화 시점을 컨트롤 하는 lateinit var와,
불변적이면서 사용시에 자동으로 초기화 되는 by lazy의 차이점이 보이시나요?
lateinit var | by lazy | |
선언 방식 | 가변적, 초기화 후 변경 가능 | 불변적(val), 초기화 후 변경 불가 |
초기화 시점 | 원하는 시점에 대입해서 명시적으로 초기화 (초기화 시점에 null이면 Exception) |
첫 사용 시 자동 초기화 |
기본타입 사용 | 기본 타입 사용 불가 | 모든 타입 사용 가능 |
스레드 안전성 | 보장하지 않음 | 보장 |
초기화 여부 확인 | ::propertyName.isInitialized로 확인 가능 | 확인 불가 |
메모리 사용 | 즉시 메모리 할당 | 사용 시점에 메모리 할당 |
용도 | 외부에서 값을 할당해야 하는 프로퍼티에 적합 | 복잡한 초기화 로직이나 객체 생성에 적합 |
lateinit var와 by lazy를 각각 살펴볼까요.
2. lateinit var
2-1. lateinit var
lateinit var는 Kotlin에서 변수의 늦은 초기화를 위해 사용되는 키워드입니다.
이 기능은 변수를 선언할 때 즉시 초기화하지 않고,
나중에 초기화할 수 있도록 해주는데요.
다음과 같은 특징들을 가지고 있습니다.
- var 키워드와 함께 사용: lateinit은 오직 var(가변) 변수에만 사용할 수 있습니다
- 초기화 지연: 변수 선언 시점에 초기화하지 않고, 나중에 초기화
- 널(null) 허용 안 함: lateinit var로 선언된 변수는 null로 초기화할 수 없습니다
- 기본 타입 제한: Int, Float, Double 등의 기본 타입(Primitive Type)에는 사용불가
lateinit var를 이용해 선언한 변수에 대해서는,
초기화가 되지 않아도 컴파일러는 아무런 에러를 보여주지 않습니다.
다만, 초기화되지 않은 상태에서,
변수에 접근하면 UninitializedPropertyAccessException을 발생시킵니다.
lateinit var는 viewBinding시 같이 사용하는 대중적인 키워드이기도 합니다.
binding을 초기화 하는 시점은,
아래와 같이, onCreate에서 개발자가 초기화하는 시점입니다.
안드로이드의 Activity를 사용하는 경우,
ViewBinding 객체의 수명이 Activity의 수명과 일치하므로,
onDestroy에서 정리되어 추가적인 null처리 작업이 필요하지 않습니다.
(다만, Fragment는 그렇지 않아서, onDestroyView에서 null처리를 해 주어야 합니다.)
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
// onDestroy()에서 별도의 null 처리 불필요
}
2-2. 초기화 확인
lateinit var는 아래와 같은 형태를 이용해,
초기화가 되었는지, 미리 확인할 수도 있습니다.
::변수명.isInitialized
3. by lazy
by lazy는 프로퍼티의 초기화를,
해당 프로퍼티가 처음 사용될 때까지 미루는 기능에 사용하는 키워드 입니다.
아래와 같은 특징을 가지고 있지요.
- 불변 프로퍼티에만 사용: by lazy는 val(불변) 프로퍼티에만 사용가능
- 프로퍼티가 처음 호출될 때 초기화
- 캐싱: 초기화 후 결과값은 캐싱되어 이후 호출 시 재사용
- 스레드 안전성: 스레드 안전을 보장
- 데이터베이스 연결, 파일 읽기 등 초기화 비용이 큰 작업에 적합
- 프로퍼티가 사용되지 않을 수도 있는 경우 조건부 초기화에 유리
코드로 어떻게 사용하는지 보겠습니다.
connection으로 선언된 변수는 초기화되지 않다가,
아래의 첫번째 사용한 시기에 초기화 되어집니다.
class DatabaseManager {
val connection by lazy {
println("커넥션 초기화...")
Database.connect("jdbc:mysql://localhost:3306/mydb", user = "root", password = "my_pass")
}
}
fun main() {
val dbManager = DatabaseManager()
println("Database manager created, but connection not yet initialized")
// 첫 번째 사용 시 초기화
println(dbManager.connection.isConnected())
// 두 번째 사용 시 이미 초기화된 connection 재사용
println(dbManager.connection.isConnected())
}
이상으로 lateinit var와 by lazy의 차이에 대해서 알아보았습니다.
'Android 개발 > Kotlin' 카테고리의 다른 글
Kotlin BuildList 사용방법 정리 (0) | 2025.02.20 |
---|---|
Kotlin Smart Cast(스마트캐스트) 총정리 (0) | 2025.01.22 |
ifEmpty 와 orEmpty 에 대해서 알아보자 # Kotlin (0) | 2023.05.30 |
CoerceIn, coerceAtMost, coerceAtLeast 범위지정 함수에 대한 정리 # Kotlin (0) | 2023.05.26 |
MapNotNull 과 MapNotNullTo 에 대한 정리 # null 제거 (0) | 2023.05.24 |
List 아이템 부분추출 함수 정리 # take, takeWhile, takeLast, drop, slice, first and last (0) | 2023.05.15 |
compareBy 와 min 그리고 sortedWith 사용방법에 대한 정리 (0) | 2023.05.10 |
any , contains, none , all, containsAll 에 대한 정리 # Kotlin list 존재여부 확인 (1) | 2023.05.06 |
Destructuring declaration 에 대해 알아보자 # 구조분해 선언 Kotlin (0) | 2023.05.01 |
Kotlin Escape 에 대한 정리 # RawString Escaped String Literal (0) | 2023.04.30 |
댓글