언어/Kotlin

Kotlin safe call

AlgoPoolJa 2022. 11. 29. 23:15

kotlin 에서는 java 와 다르게 null이 될 수 있는 타입과 null이 될 수 없는 타입을 완벽히 구분합니다. null 이 될 수 있는 타입은 일반 타입처럼 쓰고 (Int, String) null 이 될 수 있는 타입은 타입뒤에 물음표를 붙입니다.

만약 null 이 될 수 있는 타입을 호출한다면 어떻게 해야할까요? 이를 무시하고 그냥 호출한다면 NullPointerException 이 발생할 것입니다. 따라서 자바는 이때 if 를 사용해 null 을 방지합니다.

public void printStringLength(String str) {
  if (str != null) {
    System.out.println("length of str is " + str.length)
  } else {
    System.out.println("str is null")
  }
}

kotlin 에서는 이를 위해 Safe call 이란 기능을 제공합니다. Safe call 은 ?. 로 호출할 수 있습니다.

fun printStringLength(str: String) {
  val result = str?.length
  println("length of str is : ${result}")
}

출력값은 만약 str 이 null이라면 "length of str is null" 이 나오고 예를 들어 str 이 "hello" 였다면 "length of str is : 5" 가 나옵니다.

Safe call 은 chain 시에 더 유용하게 사용될 수 있습니다. 아래 코드에서 bob, department, head, name 중 하나만 null 이어도 result 는 null 이 됩니다.

val result = bob?.department?.head?.name

어떤 작업을 non-null 값만 진행해야 한다면 let 키워드와 safe call 을 같이 사용하면 됩니다.

val listWithNulls: List<String?> = listOf("Kotlin", null)
for (item in listWithNulls) {
    item?.let { println(it) } // "Kotlin" cc. null 은 무시합니다.
}

또한 safe call 은 값을 할당받기 위해 = 왼쪽에 있을 수 있습니다. 아래 예시에선 person, department 가 null 이면 함수가 호출 되지 않습니다.

person?.department?.head = managersPool.getManager()

이를 Elvis 연산자(?:)와 함께 사용되면 매우 훌륭한 기능을 사용할 수 있는데 이는 다음 포스팅에서 작성하겠습니다.

참고