개발을 하다 보면, 변수를 선언할 때 초기값을 바로 할당하지 못하는 경우가 많습니다.
lateinit 키워드를 자주 사용했지만,
왜 굳이 nullable 대신 lateinit을 써야 하는지 깊이 고민해보지 않았습니다.
이번에 공부하면서 lateinit의 필요성과 nullable과의 차이점을 명확히 이해하게 되었고,
그 내용을 정리해보았습니다.
1. lateinit 키워드의 의미와 사용 이유
lateinit은 Kotlin에서 변수를 나중에 초기화할 것임을 명시하는 키워드입니다.
이를 통해 초기화 시점을 유연하게 조정할 수 있습니다.
Kotlin은 Null Safety를 보장하기 위해 변수를 선언할 때 반드시 초기화를 요구하지만,
초기값을 바로 설정할 수 없는 경우에는 lateinit 키워드를 사용할 수 있습니다.
예시 상황:
- Android의 onCreate() 메서드 안에서 초기화가 필요한 경우
- 특정 메서드 안에서 동적으로 값을 할당해야 하는 경우
2. lateinit의 사용법
lateinit var name: String
fun initializeName() {
name = "John Doe" // 나중에 초기화
}
- lateinit을 사용하면 초기화 없이 선언할 수 있고,
나중에 필요한 시점에 초기화할 수 있습니다. - 하지만, 초기화가 되지 않은 상태에서 변수에 접근하면
UninitializedPropertyAccessException 예외가 발생합니다.
3. lateinit과 nullable의 차이
구분 | lateinit | nullable (?) |
초기화 필요 여부 | 선언 시 초기화 불필요 | 초기값 필요 (또는 null) |
null 허용 여부 | null 불가능 | null 가능 |
초기화 검사 방법 | ::varName.isInitialized 사용 | if (var != null)로 검사 |
예시 | lateinit var name: String | var name: String? = null |
lateinit은 null을 허용하지 않으면서도, 초기화 시점을 나중으로 미루고 싶을 때 사용됩니다.
4. lateinit이 사용된 코드 분석
private lateinit var graph: Array<BooleanArray>
private lateinit var visited: Array<BooleanArray>
왜 lateinit을 사용할까?
- 초기화 시점을 나중으로 미루기 위해서
예를 들어, main() 함수나 특정 초기화 메서드 안에서
graph와 visited를 크기에 맞게 동적으로 초기화할 수 있습니다.
fun initializeGraph(size: Int) {
graph = Array(size) { BooleanArray(size) }
visited = Array(size) { BooleanArray(size) }
}
초기화 여부 확인 방법:
if (::graph.isInitialized) {
println("Graph has been initialized.")
}
- ::graph.isInitialized를 통해 초기화 여부를 확인할 수 있습니다.
- 초기화 전 접근 시 UninitializedPropertyAccessException이 발생합니다.
5. lateinit 없이 사용할 경우
만약 lateinit을 사용하지 않는다면, 변수를 nullable로 선언하거나, 초기화 값을 직접 할당해야 합니다.
Nullable로 선언한 예시:
private var graph: Array<BooleanArray>? = null
fun initializeGraph(size: Int) {
graph = Array(size) { BooleanArray(size) }
}
하지만 이 경우, null 체크를 매번 해주어야 합니다.
if (graph != null) {
graph!![0][0] = true
}
- !! 연산자는 NPE (NullPointerException)를 발생시킬 위험이 있습니다.
- lateinit을 사용하면 이러한 불필요한 null 체크를 피할 수 있습니다.
6. 언제 lateinit을 사용해야 할까?
적합한 경우:
- var로 선언된 non-nullable 변수일 때
- 초기화 시점을 나중으로 미뤄야 할 때 (예: 그래프 크기, 사용자 입력 등)
- null 값을 허용하고 싶지 않을 때
부적합한 경우:
- val 변수 (변경 불가능한 변수)
- 기본 타입 (Int, Boolean 등) → lateinit 사용 불가
(Kotlin에서는 primitive 타입에 lateinit을 사용할 수 없습니다.) - 초기화가 필수적이지 않은 경우 → nullable 사용을 권장
7. 결론
lateinit은 초기화 시점을 나중으로 미루기 위한 도구로,
Nullable 변수 대신 초기화 전까지 null 상태를 피하면서도,
초기화 후에는 안전하게 사용할 수 있도록 도와줍니다.
반응형
'Android > Kotlin' 카테고리의 다른 글
[Android/Kotlin] Kotlin 컬렉션 확장 함수 정리: associateBy 사용법 (0) | 2025.03.27 |
---|---|
[Android/Kotlin] mutableMapOf vs hashMapOf 차이점 및 성능 비교 (0) | 2025.02.06 |
[Android/Kotlin] fold 사용법과 예제 (0) | 2025.02.05 |
[Android/Kotlin] 코틀린의 mutableMapOf()는 왜 LinkedHashMap을 사용할까? (0) | 2025.02.04 |
[Android/Kotlin] 코틀린 컬렉션 함수: any와 all (0) | 2025.01.21 |