질문의 배경:
엘비스 연산자 (?:)는 코틀린에서 nullable 값을 안전하게 처리하기 위한 간결한 방법으로 등장했습니다. 이 연산자는 옆에서 보면 엘비스 프레슬리의 헤어스타일과 유사해서 그런 이름이 붙었습니다. 목표는 if (a != null) a else b와 같은 템플릿 코드를 없애고 일상적인 개발을 더 편리하게 만드는 것입니다.
문제:
null일 수 있는 값에 직접 접근하면 런타임 오류 (NullPointerException)가 발생합니다. 따라서 변수에 null이 들어갔을 때 기본값을 우아하게 제공할 수 있는 도구가 필요합니다.
해결 방법:
엘비스 연산자는 nullable 타입에 적용할 수 있습니다. 연산자 왼쪽의 표현식이 null이 아닐 경우 해당 표현식을 반환하고, 그렇지 않으면 오른쪽 표현식을 반환합니다. 이는 코드를 더 간결하고 안전하게 만듭니다.
코드 예시:
fun getLength(str: String?): Int { return str?.length ?: 0 } val result = getLength(null) // result == 0 val result2 = getLength("Hello") // result2 == 5
주요 특징:
엘비스 연산자 오른쪽의 표현식이 부작용이 있을 경우 어떻게 될까요? 항상 실행되나요?
아니요! 오른쪽의 표현식은 왼쪽이 null일 때만 계산됩니다. 이는 함수가 부작용이 있거나 "비용이 많이 드는" 계산을 수행할 경우 중요한 역할을 할 수 있습니다.
코드 예시:
var called = false val x: String? = "test" val y = x ?: run { called = true; "default" } // called는 false, 왜냐하면 run은 실행되지 않기 때문입니다.
엘비스 연산자를 예외를 던지는 데 사용할 수 있나요?
네, 코틀린에서 다음과 같이 작성할 수 있습니다:
fun getLengthStrict(str: String?): Int = str?.length ?: throw IllegalArgumentException("str is null")
str가 null이면 예외가 발생합니다. 이는 데이터 검증을 위한 편리한 메커니즘입니다.
엘비스 연산자를 여러 번 연속으로 "연결"해 사용할 수 있나요?
네, 이는 fallback을 위한 일반적인 접근 방식입니다:
val name = fromDatabase ?: fromCache ?: "Unknown"
이 표현식은 첫 번째 NON-null 값을 반환하거나 "Unknown" 문자열을 반환합니다.
엘비스를 통한 다중 레벨 중첩 null 체크:
val title = a?.b?.c?.d?.e ?: defaultTitle
장점:
단점:
단계별 명확한 분해와 이해하기 쉬운 변수 이름:
val deepValue = a?.b val deeperValue = deepValue?.c?.d ?: default
장점:
단점: