본문 바로가기

개발 노트/Kotlin

[kotlin]지연 초기화

# lateinit

- 개발을 하다보면 클래스 안에서 변수만 Nullable로 미리 선언하고,  초기화를 나중에 해야 할 경우가 있다

- 이럴 경우 lateinit 키워드를 사용할 수 있다

 

 

# Nullable로 선언하는 일반적인 방법

class Person {
    var name: String? = null
    init {
        name = "Lionel"
    }
    fun process() {
        name?.plus(" Messi")
        print("이름의 길이 = ${name?.length}")
        print("이름의 첫 글자 = ${name?.substring(0, 1)}")
    }
}

 

-> 일반적인 선언 방식으로 처음에 null 값을 입력해두고, 클래스의 다른 메서드 영역에서 값을 입력한다

-> 위 방식은 변수에 입력된 값의 메서드나 프로퍼티를 사용할 때 Safe Call(?.)이 남용되어 가독성을 떨어트리는 문제가 있다

 

 

# lateinit을 사용하는 방법

- lateinit을 사용하면 Safe Call을 쓰지 않을 수 있기 때문에, 코드에서 발생할 수 있는 수많은 ? 를 방지할 수 있다

 

class Person {
    lateinit var name: String
    init {
        name = "Lionel"
    }
    fun process(){
        name.plus(" Messi")
        print("이름의 길이 = ${name.length}")
        print("이름의 첫 글자 = ${name.substring(0, 1)}")
    }
}

 

->  위의 코드를 보면 ?가 제거되면서 가독성이 좋아진 것을 확인할 수 있다

 

 

lateinit의 특징은 다음 세 가지를 들 수 있다

  • var로 선언된 클래스의 프로퍼티에만 사용할 수 있다
  • null은 허용되지 않는다
  • 기본 자료형 Int, Long, Double, Float 등은 사용할 수 없다
 

lateinit을 사용할 때는 주의할 점이 있다

  • lateinit은 변수를 미리 선언만 해 놓은 방식이기 때문에, 초기화되지 않은 상태에서 메서드나 프로퍼티를 참조하면 null 예외가 발생해서 앱이 종료됩니다
  • 따라서 변수가 초기화되지 않은 상황이 발생할 수 있다면, Nullable이나 빈 값으로 초기화하는 것이 좋다

 

 

# Lazy

- lazy는 읽기 전용 변수인 val을 사용하는 지연 초기화이다

- lateinit 입력된 값을 변경할 수 있는 반면, lazy 입력값을 변경할 수 없다 

 

class Company {
    val person: Person by lazy { Person() }
    init {
        // lazy는 선언 시에 초기화를 하기 때문에 초기화 과정이 필요 없습니다.
    }
    fun process(){
        print("person의 이름은 ${person.name}") // 최초 호출하는 시점에 초기화됩니다.
    }
}

 

-> val로 변수를 먼저 선언한 후 코드의 뒤쪽에 by lazy 키워드를 사용하면 됩니다

-> 그리고 by lazy 다음에 나오는 중괄호 { }에 초기화할 값을 써주면 된다

 

 

 

# 여기서 잠깐!!

 - by lazy를 사용하면 반환되는 값의 타입을 추론할 수 있기 때문에, 앞의 코드에서 작성한 person 변수의 타입은 생략할 수 있다

val person by lazy { Person() }

 

 

 

lazy의 특징

  • 주석에 써 있듯이 선언 시에 초기화 코드를 함께 작성하기 때문에, 따로 초기화 할 필요가 없다
  • lazy로 선언된 변수가 "최초 호출되는 시점" 에 by lazy{ } 안에 넣은 값으로 초기화 된다 
  • -> 위의 코드에서 Company 클래스가 초기화 되더라도 person에 바로 Person()으로 초기화되지 않고, process 메서드에서 person.name이 호출되는 순간 초기화 된다

lazy는 주의해서 사용해야한다

  • 지연 초기화는 말 그대로 최초 호출되는 시점에 초기화 작업이 일어나기 때문에 초기화 하는 데 사용하는 리소스가 너무 크면(메모리를 많이 쓰거나 코드가 복잡한 경우), 전체 처리 속도에 나쁜 영향을 미칠 수 있다
  • 예를 들어 위의 Company 클래스에서 처리하는 Person 클래스의 코드가 복잡하면 단순히 person.name을 호출하는 데 수 초가 걸릴 수도 있다
  • 따라서 복잡한 코드를 가지고 있는 클래스라면, 미리 초기화 해놓고 사용하는 것이 효율적이다

 

'개발 노트 > Kotlin' 카테고리의 다른 글

[Kotlin]BottomNavigation  (0) 2024.01.18
[kotlin]스코프 함수  (0) 2024.01.16
[kotlin]null 값에 대한 안정적인 처리 - Null Safety  (0) 2024.01.16
[kotlin]클래스와 설계  (0) 2024.01.16
[kotlin]함수  (0) 2024.01.16