Kotlin 공부

kotlinlang.org 내가 보려고 정리 - Null safety

3190024 2023. 8. 1. 18:22

Null safety

코틀린에서 null 값을 가질 수 있다.

null 값으로 발생할 수 있는 이슈들을 막기 위해 null safety가 있다.

런타임(실행 시간)보다는 컴파일 타임에 Null safety가 null 값으로 인해 생길 수 있는 문제들을 탐지한다.

 

-null 값을 허용할 때 명시할 수 있게 한다.

-null 값을 확인한다.

-null 값을 가지고 있을 property나 function에 safe call을 사용할 수 있게 한다.

-null 값이 탐지되었을 때 취할 행동을 선언할 수 있게 한다.

 

Nullable types

nullable type: null 값을 가질 수 있는 타입.

기본적으로는 null 값을 허용하지 않지만, 타입 선언 뒤에 ?을 붙여 nullable type을 선언할 수 있다.

 

fun main() {
    var neverNull: String = "This can't be null"
    neverNull = null // compiler error

    // String 뒤에 ?을 붙여 nullable type으로 만듦.
    var nullable: String? = "You can keep a null here"
    nullable = null // 에러 안남.

    // 타입 명시를 하지 않을 때, 기본적으로 null 값을 가질 수 없음.
    var inferredNonNull = "The compiler assumes non-null"
    inferredNonNull = null // 따라서 에러 발생.

    fun strLength(notNull: String): Int { // 이 함수는 인자로 nullabe type을 받을 수 없음.                 
        return notNull.length //반환 값도 마찬가지.
    }

    println(strLength(neverNull)) // 18.. nerverNull은 String 이므로.
    println(strLength(nullable))  // 에러 발생.. nullable은 String?이므로.
}

 

Check for null values

conditional expression으로 null 값 존재 여부를 확인할 수 있다.

fun describeString(maybeString: String?): String {
    if (maybeString != null && maybeString.length > 0) {
    	//maybeString이 null 값을 가지지 않고, 길이가 0보다 클 때
        // maybeString.length > 0 && maybeString != null 이렇게 조건문 순서 바꾸면 에러 발생.
        return "String of length ${maybeString.length}"
    } else {//maybeString이 null 값을 갖거나, 길이가 0 이하일 때
        return "Empty or null string"
    }
}

fun main() {
    var nullString: String? = null
    println(describeString(nullString))
    // Empty or null string
}

 

Use safe calls

null 값을 가질 수 있는 object의 property에 안전하게 접근하기 위해 safe call operator(?.)을 사용한다.

object의 property가 null일 때 null 반환.

 

fun lengthString(maybeString: String?): Int? = maybeString?.length
// maybeString이 null이면 null을 반환하고, 아니면 maybeString.length를 반환한다.

fun main() { 
    var nullString: String? = null
    println(lengthString(nullString))
    // null
    
    var myString: String? = "Me!"
    println(lengthString(myString))
    //3
}

safe calls은 연속될 수 있기 때문에 만약 object의 property가 null 값을 포함하는 경우에 에러 없이 null을 반환한다.

person.company?.address?.country
//person.company와 person.company.address가 nullable type일 것이다.

safe call 연산자는 extension이나 member function을 호출할 때에도 사용할 수 있다.

이 경우에 함수를 호출하기 전에 null check이 일어난다.

null 값이 발견된 경우 함수는 호출되지 않고 null을 반환한다.

fun main() {
    var nullString: String? = null
    println(nullString?.uppercase())
    // nullString이 null 값을 가지기 때문에 uppercase()를 호출하지 않고 null을 반환한다.
}

 

Use Elvis operator

Elvis operator(?:)를 사용하여 null 값이 탐지되었을 때 기본 값을 반환하게 할 수 있다.

 null 값 확인 대상 ?: null 값이 발견되었을 때 반환할 값

fun main() {
    var nullString: String? = null
    
    //nullString이 null 값을 가지기 때문에 nullString?.length는 null 값을 가지게 된다.
    // null ?: 0 으로 볼 수 있는데, ?: 왼쪽이 null 값이기 때문에 기본값인 0을 반환한다.
    println(nullString?.length ?: 0)
    // 0
}