ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Kotlin] 코틀린 Null Safety, 안전한 null 처리 방법
    Android/Kotlin 2020. 12. 27. 21:35

    코틀린의 타입 시스템은 코드에서 null references 위험을 제거하는것을 목표로 한다.
    Java를 포함한 많은 프로그래밍 가장 일반적인 오류 중 하나는 Null 참조의 멤버에 액세스하면 Null reference exception이 발생한다.

    코틀린에서 NullPointerException이 발생할 수 있는경우

    • throw NullPointerException(); 명시적 호출
    • !! 연산자 사용
    • 아래와 같은 초기화에 관한 데이터 불일치
      • 생성자에서 사용할 수 있는 초기화되지 않은 this가 전달되어 어딘가에 사용되는경우("leaking this")
      • superclass 생성자는 파생 클래스에서 구현이 초기화되지 않은 상태를 사용하는 open member를 호출
    • 자바 상호 작용
      • platform type의 null 참조로 멤버에 대한 액세스 시도
      • Java에서 MutableList와 같은 non-Null type 에 null을 추가하려는 경우
      • 외부 Java 코드로 인한 기타 문제

    코틀린 type 시스템은 null(nullable reference)을 저장할 수 있는 참조와 Null이 아닌 참조를 포함할 수 없는 참조를 구별한다. 예를 들어 문자열 유형의 일반 변수는 null을 포함할 수 없다.

    var a: String = "abc" // Regular initialization means non-null by default
    a = null // compilation error

    null을 허용하기 위해 null문자열로 String?:와 같이 선언할 수 있다.

    var b: String? = "abc" // can be set null
    b = null // ok
    print(b)

    코틀린에서의 null check

    1. 조건문으로 null check

    • Java와 같이 명시적으로 null 체크를 수행
    val l = if (b != null) b.length else -1
    val b: String? = "Kotlin"
    if (b != null && b.length > 0) {
        print("String of length ${b.length}")
    } else {
        print("Empty string")
    }

    2. Safe Calls 연산자 ?.

    val a = "Kotlin"
    val b: String? = null
    println(b?.length) 
    println(a?.length) // Unnecessary safe call
    • 위에서는 b가 null이 아니면 b.length를 반환하고, 그렇지 않으면 null을 반환한다.

    • Null이 아닌 값에 대해서만 특정 작업을 수행하려면 다음과 같이 safe call 연산자를 사용할 수 있다.

    val listWithNulls: List<String?> = listOf("Kotlin", null)
    for (item in listWithNulls) {
        item?.let { println(it) } // prints Kotlin and ignores null
    }

    3. Elvis(엘비스) 연산자 :?

    • ?:의 왼쪽에 있는 식이 null이 아니면 엘비스 연산자가 반환하고, 그렇지 않으면 오른쪽 결과를 반환한다. 왼쪽이 null인 경우에만 오른쪽 식으로 반환된다.
    // if 조건문으로 처리한 경우
    val l: Int = if (b != null) b.length else -1
    
    // 동일한 코드를 ?: 연산자 사용 시
    val l = b?.length ?: -1

     

     

    4. !! 연산자

    • 아래와 같이 !!연산자를 사용하면 값이 null인 경우 예외를 발생시킨다.
    val l = b!!.length

     

    5. Safe Casts as?

    • cast 수행 시 대상 유형이 아닌경우 ClassCastException이 발생한다.
    • as? 연산자를 사용하면 cast실패한 경우 null을 반환하여 안전하게 수행할 수 있다.
    val aInt: Int? = a as? Int

     

     

    6. 컬렉션의 Nullable Type

    • Nullable 요소 컬렉션이 있고 Null이 아닌 요소를 필터링 하려는 경우 filterNotNull()을 사용할 수 있다.
    val nullableList: List<Int?> = listOf(1, 2, null, 4)
    val intList: List<Int> = nullableList.filterNotNull()

    참조사이트

    댓글

Designed by Tistory.