관리 메뉴

피터의 개발이야기

[Kotlin] 널 안정성, Null safety 본문

Programming/Kotlin

[Kotlin] 널 안정성, Null safety

기록하는 백앤드개발자 2024. 5. 15. 10:10
반응형

 

ㅁ 들어가며

ㅇ 이 글은 코틀린 공식문서를 공부하며 번역한 글이다.

ㅇ 이 문서는  Kotlin의 Null 안정성(Null safety)에 대해 설명하고 있다.

 

ㅁ Null Safety란?

ㅇ Kotlin의 타입 시스템은 null 참조로 인한 위험을 제거하기 위해 설계되었다.

ㅇ Kotlin의 타입(type) 시스템은 Billion Dollar Mistake라고도 알려진 null 참조 코드의 위험성을 없애기 위한 것이다.

ㅇ Java를 포함한 많은 프로그래밍 언어에서 가장 일반적인 함정은 NullPointerException(줄임 NPE)이다. 

    ㄴ null 참조의 멤버에 접근하면 null 참조 예외(null reference exception)가 발생한다.

ㅇ Kotlin에서 NPE을 예방하기 위해 Nullable, Non-Nullable 타입을 구분한다.

 

ㅁ Nullable, Non-Nullable

ㅇ Nullable, Non-Nullable 두 가지 유형이 있다.

ㅇ Nullable은 null인 값을 표현할 수 있고, Non-Nullable은 null이 아닌 값만 표현할 수 있다.

var a: String = "abc"
a = null // 컴파일 에러 발생

ㅇ 컴파일 시 null이면 에러가 발생합니다.

 

// Kotlin null 표현
var number : Int? = null
var str: String? = "Hello, world"

 ㅇ null을 참조하기 위해서는 String?과 같이 선언해야 합니다.

 

ㅁ Nullable 속성 및 함수 

fun main() {
    var a: String? = "ABC"
    var b: String? = "ABC"
    var c: String? = "ABC"
    var d: String? = "ABC"

    // 스마트 캐스트(null 확인을 위해 if 문장 속에서 Non-nullable로 취급)
    if (a != null) { println(a.length) }
    
    // ?.(안전 호출 연산자)
    println(b?.length)

    // !!(강제 호출 연산자)
    println(c!!.length)
    
    // ?:(엘비스 연산자)
    d = d ?: "(Unknown)"
    println(d.length)
    
    // as?(안전한 케스팅)
    val aInt: Int? = a as? Int
    // java
    Integer aInt = (a instanceof Integer) ? (Integer) a : null;
}

 

스마트 캐스트 (if)

  ㄴ null이 아닌지를 확인하는 if 문장 속에서 Non-nullable로 취급 (스마트 캐스트)

 안전 호출 연산자 (?.)
  ㄴ ?. b가 null이 아니면 결과를 리턴하고 b가 null인 경우 null을 반환하는 안전콜

 강제 호출 연산자 (!!)

  ㄴ !!를 이용하면 강제적으로 사용할 수 있다 (실행시 에러가 발생할 수 있으므로 위험)  
엘비스 연산자 (?:)

  ㄴ 엘비스 연산자 (?:)를 사용하여 null는 되지 않도록 한다.
안전한 캐스팅 (as?)
   ㄴ 안전한 케스팅, 객체가 대상 유형이 아닌 경우 오류가 발생할 수 있다. 이런 경우 Null인지 체크하여 캐스트를 사용한다.

[참조]: devkuma - nullable

 

ㅁ Scope 함수들(let, also, run)을 사용하여 null 안전성을 확보하는 방법

let() 메서드

ㅇ 참조가 nullable이 아닌 값을 보유하는 경우에만 작업을 실행하려면 let 연산자를 사용할 수 있다.

val firstName = "Tom"
val secondName = "Michael"
val names: List<String?> = listOf(firstName, null, secondName)

ㅇ names list에 null을 포함시켰다.

 

var res = listOf<String?>()
for (item in names) {
    item?.let { res = res.plus(it) }
}

assertEquals(2, res.size)
assertTrue { res.contains(firstName) }
assertTrue { res.contains(secondName) }

ㅇ let 함수를 사용하여 이름목록의 null이 아닌 모든 요소에 대해 작업을 실행할 수 있다.

 

also() 메서드

var res = listOf<String?>()
for (item in names) {
    item?.let { res = res.plus(it); it }
  ?.also{it -> println("non nullable value: $it")}
}

ㅇ 예를 들어 null이 아닌 모든 값에 대한 로깅과 같은 몇 가지 추가 작업을 적용하려면 also () 메서드를 사용하고 이를 let()과 연결할 수 있다.

non nullable value: Tom
non nullable value: Michael

ㅇ null이 아닌 모든 요소를 ​​출력한다.

 

run() 메서드

var res = listOf<String?>()
for (item in names) {
    item?.run{res = res.plus(this)}
}

ㅇ Kotlin에는 null 허용 참조에 대해 일부 작업을 실행하는 run()가 있습니다 . 이는 let()과 매우 유사 하지만 함수 본문 내에서 Run() 메서드는 함수 매개 변수 대신  this를 참조하여 작동한다.

 

# scope function인 let, also, run은 [Kotlin] Scope Functions (let, with, run, apply, also) 정리에서도 정리하였다.

 

ㅁ 함께 보면 좋은 사이트

Kotlin의 Null 안전에 대한 종합 가이드

kotlin doc- Null safety

devkuma - Kotlin 변수 선언

반응형
Comments