코틀린의 Null

짱구·2023년 3월 12일
0

kotlin

목록 보기
2/8
post-thumbnail

널 참조의 위험성

자바를 포함한 많은 프로그래밍 언어에서 가장 많이 발생하는 예외 유형이 바로 NullPointerException 줄여서 NPE 라고도 부릅니다.

null을 발명한 토니호어는 null을 발명한 후 수십년간 수십억 달러의 시스템 오류와 피해가 발생했기 때문에 1조원짜리 실수 였다고 고백합니다.

자바에선 NPE를 줄이기 위해 JDK8에서 Optional을 지원하기 시작했습니다.

자바의 옵셔널(Optional)은 값을 래핑하기 때문에 객체 생성에 따른 오버헤드가 발생하고, 컴파일 단계에서 Null 가능성을 검사하지 않습니다.

코틀린을 비롯한 최신 언어에선 널 가능성을 컴파일러가 미리 감지해서 NPE 가능성을 줄일 수 있습니다.

코틀린에서 NPE를 해결하는 다양한 방법

코틀린은 언어적 차원에서 NPE가 발생할 가능성을 제거합니다.
코틑린의 타입은 기본적으로 Non-Null 타입이므로 null을 허용하지 않습니다.

val a : String = null // 컴파일 오류
var b : String = "aabbcc"
b = null // 컴파일 오류

코틀린은 null을 허용하는 Nullable 타입을 제공하며 Nullable 참조는 컴파일 단계에서 널 안정성을 제공합니다.

var a : String? = null // Nullable 타입
 println("a.length = ${a.length}") // 컴파일 오류

Nullable 참조에 대한 접근은 안전 연산자를 사용합니다.

    var a : String? = null
    println("a?.length = ${a?.length}")
    // 출력 : a?.length = null

엘비스 연산자( ?: )를 사용해 null이 아닌 경우 특정 값을 사용하도록 할 수 있습니다.

val b : Int = if (a != null) a.length else 0
// 엘비스 연산자를 사용하면 좌변이 null인 경우 우변을 리턴한다
val b = a?.length ?: 0
  • 자바와 코틀린의 null 처리를 비교해보겠습니다.

자바의 null 처리 코드

public class Java_NullSafety {
  public static String getNullStr() {
    return null;
  }
  
  public static int getLengthIfNotNull(String str) {
    if (str == null || str.length() == 0) {
      return 0;
    }
    return str.length();
  }
  
  public static void main(String[] args) {
  
    String nullableStr = getNullStr();
    
    // Optional사용
    nullableStr = Optional.ofNullable(nullableStr).orElse("null인 경우 반환");
    // Optional을 주석처리하고 null 참조를 사용하더라도 컴파일 오류가 발생하지 않음
    
    int nullableStrLength = nullableStr.length();
    System.out.println(nullableStrLength); // 11 반환
    
    // 메서드 내부에서 null을 검사하는 방법도 있다
    int length = getLengthIfNotNull(null);
    System.out.println(length); // 0 반환
  }
}

코틀린의 null 처리 코드

fun getNullStr(): String? = null

fun getLengthIfNotNull(str: String?) = str?.length ?: 0

fun main() {
  val nullableStr = getNullStr()
  
  val nullableStr = getNullStr() ?: "null인 경우 반환"
  println(nullableStr)
  
  // val nullableStrLength = nullableStr.length // 컴파일 오류
  // println(nullableStrLength)

  println(getLengthIfNotNull(null))
}

이와 같이 코틀린에서는 null처리가 자바보다 더 간결하고 null을 더 안정적으로 처리할 수 있다고 봅니다.

코틀린에서도 NPE가 발생할 수 있다!!!

// 명시적 NPE 호출
throw NullPointerException()

// !! = NotNull임을 단언하는 단언 연산자, !!를 사용
val c: String? = null
val d = c!!.length

이외에도 자바와 상호운용하는 경우 자바에서 NPE를 유발하는 코드를 코틀린에서 사용하면 NPE가 발생할 수 있습니다.

println(Java_NullSafety.getNullStr().length) // 위에 예시 코드
//Exception in thread "main" java.lang.NullPointerException 발생!!

코틀린에서 자바 코드를 사용할때는 항상 Nullable 가능성을 염두해 안전 연산자와 엘비스 연산자를 사용하는걸 권장합니다.

println(Java_NullSafety.getNullStr()?.length)

출처 : fastcampus

profile
코드를 거의 아트의 경지로 끌어올려서 내가 코드고 코드가 나인 물아일체의 경지

0개의 댓글