일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- Android
- 타이쿤
- GIT
- 게임개발
- java
- 2d게임
- 쿼터뷰
- 개발
- 티스토리
- Android Studio
- 유니티
- Unity
- 안드로이드
- gitlab submodule
- github submodule
- 서브모듈 pull
- submodule sourcetree
- 목서버
- 서브모듈 sourcetree
- 카페오냥
- 내 맘대로 정리한 안드로이드
- 안드로이드개발
- 코틀린
- 앱개발
- github
- DataBinding
- Kotlin
- 앱
- firebase
- 안드로이이드 submodule
- Today
- Total
Uing? Uing!!
[내 맘대로 정리한 Kotlin] lateinit과 by lazy의 차이점 본문
늦은 초기화
가끔 클래스 안에서 '내가 이 변수를 쓸 것이다'라고 선언만 해 놓고,
나중에 값을 사용할 수 있게 되면 그 때 값을 입력해 주고 싶을 때가 있다.
이럴 때 사용 가능한 방법 중에는 아래와 같이 일단 null로 설정해 준 뒤 나중에 바꾸는 방법이 있기는 하다.
var x : String? = null
하지만 두 가지, 마음에 걸리는 상황이 생길 수 있다.
1) x의 값이 변할 수는 있지만, 절대 null이어서는 안 되는 경우 -> 처음에 nullable한 <String?>으로 초기화해주는 것이 부적절함
2) x의 값이 처음 한 번만 정해지면 다시는 변하지 않는 경우 -> x가 var일 이유가 없음
애초에 '나중에 쓸 것'이라는 걸 알고 있는데, '왜 처음에 null로 고정을 해 주어야 하냐?' 라는 문제다.
이럴 때를 위해 제공되는 문법이 lateinit, 그리고 by lazy이다.
lateinit
lateinit은 이렇게 사용된다.
lateinit var x : String
x = "Initialized"
println(x)
처음에 var 형태의 x가 나중에 사용될 것이며, String 타입이라는 것만 정해 준다.
그리고 이후에 사용할 때에 값을 지정해 주면 x에 값이 들어간다.
이 lateinit을 처음 제시된 방법과 비교했을 때, 가장 큰 차이점은 x가 String? 타입이 아닌 String 타입이라는 점이다.
x가 null이 될 수 없기 때문에, 이후에 x = null와 같이 선언해 주면 에러가 발생한다.
또한 x에 값이 들어가기 전에 x는 null이 아니라 uninitialized(초기화되지 않음) 상태로 존재한다.
이 상태에서 x를 바로 사용하려고 한다면 초기화되지 않았다는 에러가 발생하게 된다.
따라서 lateinit으로 변수를 선언해 주었다면 사용 전에 꼭 초기화 단계를 거쳐야 한다.
* 단, lateinit의 경우에는 Int, Long, Double, Float와 같은 Primitive Type에 대해서는 사용할 수 없다.
by lazy
by lazy는 이렇게 사용된다.
val x : String by lazy { "Initialized!" }
println(x)
처음에 val 형태의 x가 나중에 사용될 것이며, '사용 시에' 어떤 값이 들어가는지를 정해 준다.
이후에 따로 지정할 필요는 없고, 두 번째 줄과 같이 x를 사용하는 첫 순간에 x에 값이 들어간다.
이 코드에서는 사실 by lazy가 필요하지는 않다. 초기화될 값이 정해져 있기 때문이다.
하지만 만약 x가 다른 계산식의 영향을 받거나, 다른 변수의 초기화 이후에만 값을 알 수 있다면 이 방식을 사용할 수 있다.
이를테면 이런 상황이다.
lateinit var inputValue : String
val x : Int by lazy { inputValue.length }
inputValue = "Initialized!"
println(x)
이 코드의 경우, x는 inputValue라는 문자열의 길이를 받아와야 한다.
그런데 inputValue는 lateinit으로 설정되어 있기 때문에, 아직 그 길이를 알 수가 없다.
무조건 inputValue가 제대로 값을 가지게 된 후에 x를 활용할 예정이라면, 이 때 이용할 수 있는 문법이 by lazy다.
x는 변수가 '처음 사용되는 순간'인 4번째 줄의 출력문에서 inputValue.length로 초기화된다.
x를 사용하기 전에 inputValue 친구만 초기화를 해 주었다면,
어디에서 호출하든 특별히 추가적인 선언문을 작성할 필요가 없는 것이다.
lateinit vs by lazy
위에서 살펴보았듯이 lateinit과 by lazy는 유사한 점이 많다.
특히 값을 나중에 초기화한다는 기본적인 목적은 같다고 볼 수 있다.
하지만 두 문법의 특성과 각각을 사용하는 상황에는 몇 가지 차이점이 있고,
그중 가장 큰 차이점은 lateinit은 var로만, by lazy는 val로만 선언된다는 점이다.
이렇기 때문에 초기화 이후에 값이 변할 수 있는 변수에는 lateinit을,
처음 초기화 된 직후부터 계속 read-only로만 쓰이는 변수에는 by lazy를 사용하는 것이 좋다.
'Kotlin' 카테고리의 다른 글
[내 맘대로 정리한 Kotlin] @JvmOverloads: constructor를 일일이 상속받아 만들기 귀찮다면! (0) | 2021.03.30 |
---|---|
[내 맘대로 정리한 Kotlin] 확장 함수와 확장 프로퍼티: 직접 수정할 수 없는 클래스에 함수&프로퍼티 추가하기 (2) | 2020.12.13 |
[내 맘대로 정리한 Kotlin] vararg(가변인자)로 파라미터 원하는 개수만큼 받기 (0) | 2020.12.11 |
[내 맘대로 정리한 Kotlin] let으로 null-check 하기 (0) | 2020.11.17 |
[내 맘대로 정리한 Kotlin] isEmpty와 isBlank의 차이점 (0) | 2020.09.30 |