커니의 코틀린 책의 내용을 요약한 글입니다.
자바의 널(null) 처리
프로그래밍을 하면서 가장 많이 마주치는 버그 중 하나로 NPE(null pointer exception) 를 들 수 있을 것입니다.
자바에서는 NPE 를 방지하기 위해 어노테이션의 도움을 받아 널 허용 여부를 다음과 같이 구분합니다.
// 널 값을 허용
@Nullable
String name;
// 널 값을 허용하지 않음
@NonNull
String name;
그러나 어노테이션으로 널 어용 여부를 확인하는 것은 Android Lint 와 같은 정적 분석 도구에서 지원하는 기능이기 때문에 여전히 NPE(null pointer exception) 가 발생할 여지가 있습니다.
위의 코드에서도 보다시피 NonNull 로 선언한 변수를 초기화하지 않아도 Lint 가 경고만 해 줄 뿐, 컴파일 단계에서 오류가 발생하지 않습니다. 이 변수를 어딘가에서 널이 아니라는 가정하에 사용한다면, 당연히 NPE 가 발생할 것입니다.
코틀린의 널(null) 처리
코틀린에서는 이러한 문제점을 해결하기 위해 모든 타입에 명시적으로 널 허용 여부를 함께 표기하도록 합니다.
별도 표기가 없는 타입은 널 값을 허용하지 않고, 타입 뒤에 ? 를 붙여주면 해당 변수는 널 값을 가질 수 있게 됩니다.
// 널 값을 허용
val name: String?
// 널 값을 허용하지 않음
// 초기화하지 않거나, null 을 대입할 경우 컴파일 에러
val name: String = "Bob"
코틀린에서는 널 값을 가질 수 없는 변수를 초기화하지 않거나, null 을 대입할 경우 컴파일 에러가 발생하기 때문에 자바에 비해 널 처리를 더욱 신뢰성있게 할 수 있고, NPE 가 발생할 위험이 낮아집니다.
자바로 작성된 클래스의 널 처리
일부 자바 자료형은 다음과 같이 코틀린의 자료형으로 처리됩니다.
타입 뒤의 ! 는 해당 타입이 널 허용 여부에 대한 정보를 포함하지 않음을 나타내며 플랫폼 타입이라고 부릅니다.
Java |
Kotlin |
java.lang.Annotation |
kotlin.Annotation! |
java.lang.CharSequence |
kotlin.CharSequence! |
java.lang.Cloneable |
kotlin.Cloneable! |
java.lang.Comparable |
kotlin.Comparable! |
java.lang.Enum |
kotlin.Enum! |
java.lang.String |
kotlin.String! |
java.lang.Throwable |
kotlin.Throwable! |
플랫폼 타입은 자동으로 지정되는 타입으로 개발자가 직접 사용할 수 없습니다. 플랫폼 타입의 객체는 널이 될 수 있는 타입과 될 수 없는 타입에 자유롭게 할당할 수 있습니다. 그러나 null 값을 가지는 객체를 널이 될 수 없는 타입에 대입하면 NPE 가 발생할 수 있기 때문에 플랫폼 타입의 객체를 사용할 경우에는 항상 객체의 널 여부를 확인해주어야 합니다.
이러한 불편함 때문에 자바에서 널리 쓰이는 어노테이션을 코틀린이 자동으로 인식해서 널이 될 수 있는 타입과 될 수 없는 타입을 구분해주지만, 코틀린으로 작성되지 않은 곳(예를들어, JSON 파싱 결과)에서 생성된 플랫폼 타입의 객체는 널 여부를 검증할 수 없기 때문에 항상 주의해야 합니다.
'Kotlin > 커니의 코틀린' 카테고리의 다른 글
13장. Rxjava 적용하기 (0) | 2020.09.25 |
---|
댓글