널 가능성(nullability) 은 NullPointerException(NPE) 오류를 피할 수 있게 돕기 위한 코틀린 타입 시스템의 특성이다. 널이 될 수 있는지 여부를 타입 시스템에 추가함으로써 컴파일러가 여러 가지 오류를 컴파일 시 미리 감지해서 실행 시점에 발생할 수 있는 예외의 가능성을 줄일 수 있다.
코틀린과 자바의 첫 번째이자 가장 중요한 차이는 코틀린 타입 시스템이 널이 될 수 있는 타입을 명시적으로 지원한다는 점이다.
int strLen(String s) {
return s.length();
}
위 함수는 안전할까? 이 함수에 null을 넘기면 NPE가 발생한다. 이 함수를 코틀린으로 다시 작성해보자. 널이 인자로 들어올 수 없다면 코틀린에서는 다음과 같이 함수를 정의할 수 있다.
fun strLen(s: String) = s.length
strLen에 null이거나 널이 될 수 있는 인자를 넘기는 것은 금지되며, 혹시 그런 값을 넘기면 컴파일 시 오류가 발생한다.
이 함수가 널과 문자열을 인자로 받을 수 있게 하려면 타입 이름 뒤에 물음표(?)를 명시해야 한다.
fun strLenSafe(s: String?) = ...
널이 될 수 있는 타입인 변수에 대해 변수.메소드()처럼 메소드를 직접 호출할 수는 없다.
fun strLenSafe(s: String?) = s.length
// Only safe (?.) or non-null asserted (!!.) calls are allowed
// on a nullable receiver of type String?
널이 될 수 있는 타입의 값을 널이 될 수 없는 타입의 파라미터를 받는 함수에 전달할 수 없다.
val x: String? = null
val y: String = x // Type mismatch
널이 될 수 있는 타입의 값을 널이 될 수 없는 타입의 파라미터를 받는 함수에 전달할 수 없다.
val x: String? = null
strLen(x) // Type mismatch.
위키피디아에 타입을 다음과 같이 정의하고 있다.
“타입은 분류(classification)로 … 타입은 어떤 값들이 가능한지와 그 타입에 대해 수행할 수 있는 연산의 종류를 결정한다.”