그동안은 코틀린의 문법 중 넓은 범위의 것들을 살펴보았다. 이제 가장 중요한 부분을 배워보자: 바로 타입 시스템이다. 코틀린에서는 새롭게 만들어진 기능, 즉 nullable 타입과 read-only collection 등을 지원한다.
코틀린 타입 시스템에서는 자바에서 흔히 볼 수 있는 java.lang.NullPointerException
를 피할 수 있기 위해서 컴파일 시점에 null 에러를 파악할 수 있도록 명시적으로 지원한다.
/* Java */
int strLen(String s) {
return s.length();
}
자바에서는 위와 같은 함수에서 String이 null일 경우 NullPointerException 에러를 만들지만, 코틀린의 경우 String 타입이 반드시 넘겨지도록 강제하기 때문에 null이 포함된 매개변수를 넘겨 줄 수 없다. 만약 코틀린에서 null을 넘겨주고 싶다면 이를 **앨비스 연산자 ?
**를 사용하여 보여줘야 한다.
fun strLen(s: String) = s.length
>>> strLen(null)
ERROR: Null can not be a value of a non-null type String
//명시적으로 null 타입을 넘겨주기 때문에 ? 사용
un strLenSafe(s: String?) = ...
null 타입을 명시한 후에는 할 수 있는 일이 제한되어 있다.
fun strLenSafe(s: String?) = s.length()
처럼 메소드 호출 불가val x: String? = null
처럼 null 할당 불가단, if를 통해 null을 체크해 준 다음에는 컴파일러가 컴파일 하는 것이 가능하다.
fun strLenSafe(s: String?): Int =
if (s != null) s.length else 0
타입이란 “해당 타입에 대해 가능한 값들을 집합으로 모아 놓은 분류”
이다.
자바에서는 String 타입에서 String 값과 null 값 둘 중에 하나를 가질 수 있다. 따라서 이런 경우 추가적인 타입 체크가 필요하다.
<aside>
📌 자바에서도 @Nullable
나 @NotNull
를 활용하여 null 타입 체크가 가능하지만, 이는 별로 유용하지 않다. 또 다른 해결법은 Optional
class를 활용하여 null 타입을 감싸는 것이지만, 이는 더 복잡한 코드를 생성하게 된다.
</aside>
이러한 자바의 문제점을 코틀린은 Nullable
타입을 제공함으로써 손쉽게 해결 가능하다. Nullable
과 None-null
을 구분함으로 인해 어떠한 값이 어떤 계산을 할 수 있는지 명확하게 이해할 수 있다.
해당 연산자는 null 체크와 동시에 메소드를 호출하는 역할을 한다.
s?.toUpperCase()
//같은 의미
if (s != null) s.toUpperCase() else null.