학습할 내용

  • null의 정의
  • null을 허용하는 유형과 null을 허용하지 않는 유형의 차이점
  • null 안전의 정의 및 중요성, Kotlin이 null 안전을 달성하는 방법
  • ?. 안전 호출 연산자와 null이 아닌 !! 어설션 연산자와 함께 null 허용 변수의 메서드와 속성에 액세스하는 방법
  • if/else 조건문으로 null 검사를 실행하는 방법
  • if/else 표현식을 사용하여 null을 허용하는 변수를 null을 허용하지 않는 유형으로 변환하는 방법
  • null을 허용하는 변수가 null인 경우 if/else 표현식 또는 ?: 엘비스 연산자를 사용하여 기본값을 제공하는 방법

null을 허용하는 변수 사용

null의 정의

Kotlin에서는 null을 사용하여 변수와 연결된 값이 없음을 나타낼 수 있습니다.

Kotlin 플레이그라운드를 열고 기존 코드를 다음 프로그램으로 바꿉니다.

fun main() {
    val favoriteActor = null
    println(favoriteActor)
}

출력은 다음 코드 스니펫과 같습니다.

null

null을 사용한 변수 재할당

val 키워드를 var 키워드로 변경한 후 favoriteActor 변수를 String 유형으로 지정합니다.

fun main() {
    var favoriteActor: String = "Sandra Oh"
    println(favoriteActor)
}

favoriteActor 변수에 null을 재할당한 다음 프로그램을 실행합니다.

fun main() {
    var favoriteActor: String = "Sandra Oh"
    println(favoriteActor)

    favoriteActor = null
}

다음 오류 메시지가 표시됩니다.

Null cannot be a value of a non-null type 'String'.

Kotlin에서는 null을 허용하는 유형과 null을 허용하지 않는 유형이 있습니다. null을 보유하도록 명시적으로 지정하는 경우에만 null을 허용하는 유형입니다. 오류 메시지에서 알 수 있듯이 String 데이터 유형은 null을 허용하지 않는 유형이므로 변수에 null을 재할당할 수 없습니다. Kotlin에서 null을 허용하는 변수를 선언하려면 유형 끝에 ? 연산자를 추가해야 합니다.

favoriteActor 변수 유형을 String? 데이터 유형으로 변경합니다.

fun main() {
    var favoriteActor: String? = "Sandra Oh"
    println(favoriteActor)

    favoriteActor = null
    println(favoriteActor)
}

출력은 다음 코드 스니펫과 같습니다.

Sandra Oh
null

null을 허용하는 변수 처리

이 섹션에서는 . 연산자를 사용하여 null을 허용하는 변수의 메서드와 속성에 액세스하는 방법을 알아봅니다.

main() 함수의 코드를 모두 삭제한 후 String 유형의 favoriteActor 변수를 선언하고 좋아하는 배우의 이름을 할당합니다.

fun main() {
    var favoriteActor: String = "Sandra Oh"
}

length 속성을 사용하여 favoriteActor 변수 값의 글자 수를 출력한 다음 이 프로그램을 실행합니다.

fun main() {
    var favoriteActor: String = "Sandra Oh"
    println(favoriteActor.length)
}

예상대로 출력됩니다.

9

null을 허용하는 변수의 속성에 액세스

favoriteActor 변수를 null을 허용하는 유형으로 변경한 다음 이 프로그램을 실행합니다.

fun main() {
    var favoriteActor: String? = "Sandra Oh"
    println(favoriteActor.length)
}

다음 오류 메시지가 표시됩니다.

Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type 'String?'.

코드의 문법 오류로 코드를 컴파일할 수 없을 때 발생하는 컴파일 오류입니다. 변수의 멤버에 액세스하는 경우 그 변수는 null일 수 없습니다. 이 조건이 중요한 이유는 앱 실행 중에 null인 변수의 멤버에 액세스하려는 시도가 있는 경우 null 변수에 속성이나 메서드가 포함되어 있지 않으므로 앱이 비정상 종료되기 때문입니다. 이러한 유형의 장애를 런타임 오류라고 하며, 코드를 컴파일하고 실행한 후에 발생하는 오류입니다. Kotlin 컴파일러가 null을 허용하는 유형에 관해 null 검사를 강제하므로 이러한 런타임 오류가 방지됩니다.

?. 안전 호출 연산자 사용

?. 안전 호출 연산자를 사용하여 null을 허용하는 변수의 메서드나 속성에 액세스할 수 있습니다. Kotlin 컴파일러는 null 참조에 관한 멤버 액세스 시도를 중지하고 액세스된 멤버의 null을 반환합니다.

println() 문에서 . 연산자를 ?. 안전 호출 연산자로 대체합니다.

fun main() {
    var favoriteActor: String? = "Sandra Oh"
    println(favoriteActor?.length)
}

프로그램을 실행합니다.

9

favoriteActor 변수를 null 로 재할당한 다음 실행합니다.

fun main() {
    var favoriteActor: String? = null
    println(favoriteActor?.length)
}

다음과 같이 출력됩니다.

null

null이 아닌 어설션 연산자 !! 사용

null이 아닌 !! 어설션 연산자를 사용하여 null을 허용하는 변수의 메서드나 속성에 액세스할 수 있습니다. ?. 안전 호출 연산자와 달리 null이 아닌 !! 어설션 연산자를 사용하면 null을 허용하는 변수가 실제로 null일 때 NullPointerException 오류가 발생할 수 있습니다.

favoriteActor 변수에 좋아하는 배우의 이름을 재할당한 후 println() 문에서 ?. 안전 호출 연산자를 null이 아닌 !! 어설션 연산자로 대체합니다.

fun main() {
    var favoriteActor: String? = "Sandra Oh"
    println(favoriteActor!!.length)
}

프로그램을 실행합니다.

9

favoriteActor 변수를 null 로 재할당한 다음 프로그램을 실행합니다.

fun main() {
    var favoriteActor: String? = null
    println(favoriteActor!!.length)
}

NullPointerException 오류가 발생합니다.

Exception in thread "main" java.lang.NullPointerException
 at FileKt.main (File.kt:3) 
 at FileKt.main (File.kt:-1) 
 at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (:-2) 

변수가 null이 아님이 확실하지 않다면 !! 연산자를 사용하지 않는 것이 좋습니다.

if/else 조건문 사용

favoriteActor 변수에 좋아하는 배우의 이름을 재할당한 후 println() 문을 삭제합니다. favoriteActor != null 조건이 있는 if 브랜치를 추가합니다.

fun main() {
    var favoriteActor: String? = "Sandra Oh"

    if (favoriteActor != null) {
      println("The number of characters in your favorite actor's name is ${favoriteActor.length}.")
    }
}

프로그램을 실행합니다.

The number of characters in your favorite actor's name is 9.

favoriteActor 변수가 null인 상황을 처리하려면 else 브랜치를 추가합니다. favoriteActor 변수를 null 로 할당한 다음 프로그램을 실행합니다.

fun main() {
    var favoriteActor: String? = null

    if (favoriteActor != null) {
      println("The number of characters in your favorite actor's name is ${favoriteActor.length}.")
    } else {
      println("You didn't input a name.")
    }
}

예상대로 출력됩니다.

You didn't input a name.

if/else 표현식

lengthOfName 변수를 만들어 if/else 표현식을 할당합니다.

fun main() {
    var favoriteActor: String? = "Sandra Oh"

    val lengthOfName = if (favoriteActor != null) {
      println("The number of characters in your favorite actor's name is ${favoriteActor.length}.")
    } else {
      println("You didn't input a name.")
    }
}

println()문을 삭제하고 다음과 같이 수정합니다.

fun main() {
    var favoriteActor: String? = "Sandra Oh"

    val lengthOfName = if (favoriteActor != null) {
      favoriteActor.length
    } else {
      0
    }

    println("The number of characters in your favorite actor's name is $lengthOfName.")
}

프로그램을 실행합니다.

The number of characters in your favorite actor's name is 9.

?: Elvis 연산자 사용

?: Elvis 연산자를 사용하면 ?. 안전 호출 연산자가 null을 반환할 때 기본값을 추가할 수 있습니다.

val 변수이름 = null_허용_변수?.메서드_또는_속성 ?: 기본값

변수가 null이 아닌 경우에는 앞의 표현식이 실행되고, null이면 뒤의 표현식이 실행됩니다.

다음과 같이 코드를 수정한 후 실행합니다.

fun main() {
    var favoriteActor: String? = "Sandra Oh"

    val lengthOfName = favoriteActor?.length ?: 0

    println("The number of characters in your favorite actor's name is $lengthOfName.")
}

앞의 출력과 동일하게 출력됩니다.

정리

  • 변수를 null로 설정하여 변수에 값이 없음을 나타낼 수 있습니다.
  • null을 허용하는 변수의 메서드나 속성에 액세스하려면 ?. 연산자나 !! 연산자를 사용해야 합니다.
  • null을 허용하는 변수가 null인 경우 if/else 표현식 또는 ?: Elvis 연산자로 기본값을 제공할 수 있습니다.

📚 참고: Android Developers 공식 Kotlin 학습 자료 본 글은 Android Developers의 Kotlin 교육 콘텐츠를 참고하여 재구성했습니다.

카테고리:

업데이트:

댓글남기기