null이란 값이 없음을 의미하는 것으로 토니 호어가 고안했다고 한다.
10억 불짜리 실수'(billion dollar mistake)라고 회고했다고 한다
이 null을 초기화 해주지 않고 참조할 경우 프로그램 종료와 함께
시뻘건 exception을 맞닥뜨리게 되는데
이를 NPE(Null Pointer Exception)라고 한다.
Kotlin에선 이 NPE로 인한 오작동을 줄이고자
null safety 개념을 도입하였는데
Java처럼 일반적인 방법의 null 선언을 불허한다.
Kotlin에서는 기본이 Non-null이다.
아래와 같이 작성해보면..
var a: Int = null // error
println(a)
Null can not be a value of a non-null type int
변수 a가 non-null type인 int이기 때문에 null이 될 수 없다고 한다.
그렇다면 Kotlin에서 null 선언은 못하는 것인가?
그것은 아니니 걱정하지 않아도 된다.
var a: Int? = null
println(a) // output null
데이터타입에 물음표(?)를 붙여주면 Nullable type으로 만들 수 있다.
var a: String? = null
println(a.length) // returned null
위와 같이 nullable string인 a의 멤버나 메소드를 호출하려고 하면
스튜디오에서 에러메세지를 뿜을 것이다.
nullable type은 멤버나 메소드 호출 같은 체이닝을 할 때
? 연산자를 붙여야한다.
var a: String? = null
var b: String? = "Velog"
var c: String = "JeepChief"
println(a?.length) // null
println(b?.length) // output 5
println(c.length) // output 9
a는 null이기 때문에 null을 반환하고
b는 null이 아니기 때문에 length를,
c는 non-null이기 때문에 ?. 연산자 없이도 정상적으로 length를 반환한다.
!! 연산자는 해당 nullable type의 값이
null이 아니라는 것을 보장하고
명시적으로 non-null 타입을 반환하지만
null 일 경우에는 NPE를 throw한다.
그렇기 때문에 null이 아니라고 확실시 되는 경우에만
사용할 것을 권장한다.
시뻘건 exception을 마주볼 수도 있다
var a: String? = "Kotlin"
var b: String? = null
println(a!!.length) // output 6
println(b!!.length) // throw NPE
무섭다 무서워
이른바 엘비스 연산자라고 불리는데
연산자를 눕혀서 보면 미국의 가수 엘비스 프레슬리의 머리와 닮았다고 하여
붙여진 이름이다.
연산자를 기준으로 왼쪽의 값이 null이면
오른쪽의 값을 반환하는 연산자이다.
조금 쉽게 생각하자면..
삼항 연산자의 null 버전이라고 생각해도 될 거 같다.
var a: Int? = null
println(a ?: 100) // output 100
위 코드를 보면 a는 null이기 때문에
엘비스 연산자의 오른쪽에 있는 100이 반환되어
println()
으로 100이 출력된다.
Kotlin의 null safety는 위에서도 언급했듯이
NPE를 방지하고자 도입된 개념이다.
언어 자체에서 다양한 방법으로 NPE를 대처하는 방안을
제시해주니 NPE에 대해 유연한 대응을 할 수 있어서
앱의 완성도가 높아지는 결과를 가져온다.
이 포스팅은 필자가 배운 것을 토대로 정리한 것이라
모자라거나 틀린 내용도 있을 수 있으니
자세한 내용은 공식 문서를 참고하는 것이 좋겠다.
개인적으로 공부했던 것을 바탕으로 작성하다보니
잘못된 정보가 있을수도 있습니다.
인지하게 되면 추후 수정하겠습니다.
피드백은 언제나 환영합니다.
읽어주셔서 감사합니다.