[Kotlin] 코틀린에서 null을 다루는 방법 - null 체크, Safe Call, 엘비스 연산자, null 아님 단언, lateinit

김효권·2023년 4월 5일
post-thumbnail

인프런 자바 개발자를 위한 코틀린 입문(https://www.inflearn.com/course/java-to-kotlin) 강의를 듣고 내용을 정리하였습니다🤣

코틀린과 자바의 가장 큰 차이는 코틀린 타입 시스템이 null이 될 수 있는 타입을 명시적으로 지원한다는 점이다. 코틀린에서는 nullable한 변수에 대한 처리를 하지 않으면 애초부터 컴파일 에러가 발생하므로 많은 오류를 사전에 방지할 수 있다.

코틀린에서의 null 체크

public boolean startsWithA(String str) {
    return str.startWith("A");
}

위 코드에서 strnull로 넘어온다면, NPE가 발생하게된다. Kotiln에서는 이 Java코드를 어떻게 개선할 수 있을까🧐

fun startsWithA(str: String?): Boolean {
	if (str == null) {
    	throw new IllegalArgumentExcetion("null이 들어왔습니다.")
    }
    retrun str.startWith("A")
}

위 kotlin 코드에서 타입 앞에 ?를 붙여 nullable하다는 것을 명시해주었고, null 처리 로직을 추가해주었다. null 처리 로직이 존재하지 않는 경우 컴파일 에러가 발생하기때문에 실행조차 하지 못한다!!

Safe Call

val str: String? = "ABC"
str.length	// null이 아니라면 그대로 실행하고
str?.length	// null이라면 실행하지 않는다.(그대로 null)

null이 될 수 있는 변수에 대해서는 수행할 수 있는 연산이 제한된다. null 처리 로직을 수행하거나 Safe Call(?.)을 사용한다.

엘비스 연산자(Elvis Operator)

val str: String? = "ABC"
str?.length ?: 0

앞의 연산 결과가 null이면 뒤의 값을 사용한다. 엘비스 연산자를 통해 바로 예외를 반환하거나 다음 로직을 실행하는 등 다양한 방법으로 사용할 수 있다.

  1. early return
fun calculate(number: Long?): Long {
	number ?: return 0
    // 다음 로직
 }
  1. 예외 발생
fun calculate(number: Long?): Long {
	number ?: throw new IllegalArgumentExcetion("null이 들어왔습니다.")
    // 다음 로직
 }

null 아님 단언

fun startsWithA(str: String?): Boolean {
    retrun str!!.startWith("A")
}

!! 키워드를 사용한다. str 변수에 절대 null이 들어올 수 없다고 명시하는 키워드이다.

Lazy Loading

객체 인스턴스를 일단 nullable로 생성한 다음에 나중에 초기화하는 경우가 많다. 이런 경우에는 !!을 사용하거나 해당 객체 인스턴스에 접근하기 위해 null 검사 로직을 사용해야한다.

  1. !! 연산자 사용
class MySerivce {
	fun performAction(): String = "foo"
}
class MyTest {
	private var mySerivce: MyService? = null // 일단 null로 초기화한다.
    
    @Before
    fun setUp() {
    	myService = MyService()	// setUp 메서드를 통해 진짜 초깃값을 지정한다.
    }
    
    @Test
    fun testAction() {
    	// 반드시 null이 들어올 수 있다는 것을 신경 써야한다. !!나 ?를 꼭 써야한다.
    	Assert.assertEquals("foo", myService!!.performAction())
    }
}

만약 프로퍼티를 여러번 사용하는 경우 코드가 더욱 나쁘게 변한다. 이를 해결하기위해 myService 프로퍼티를 나중에 초기화할 수 있다. → lateinit

  1. lateinit 사용하기
class MySerivce {
	fun performAction(): String = "foo"
}
class MyTest {
	private lateinit var mySerivce: MyService	// lateinit를 붙여준다.
    
    @Before
    fun setUp() {
    	myService = MyService()	// setUp 메서드를 통해 초기화한다.
    }
    
    @Test
    fun testAction() {
    	// null 검사를 수행하지 않고 프로퍼티를 사용한다.
    	Assert.assertEquals("foo", myService!!.performAction())
    }
}

lateinit 키워드를 사용한 프로퍼티에 접근하려고 하면 lateinit property myService has not been initialized 라는 예외가 발생한다.

참고

Kotlin In Action
인프런 자바 개발자를 위한 코틀린 입문(https://www.inflearn.com/course/java-to-kotlin)

0개의 댓글