코틀린은 null이 들어갈 수 있는 변수를 아예 다른 타입으로 취급한다고 했다.
코틀린에서 null을 어떻게 다루는 지 알아보자.
null
Java
1
2
3
public boolean startsWithA(String str) {
return str.startsWith("A");
}
위 코드는 안전할까?
그렇지 않다.
String str 변수에 null 값이 들어갈 수 있기 때문이다. nullPointerException이 발생하게 된다.
Java에서는 이를 어떻게 대처하는지 보자.
- str이 null일 경우 Exception을 발생시킨다.
- str이 null일 경우 null을 반환한다.
- str이 null일 경우 false를 반환한다.
Kotlin
kotlin null 체크
- null값이 포함될 수 있으므로 ?를 붙여준다.
- 반환형에도 null이 들어갈 수 있다면 ?를 붙여주어야 한다.
코틀린에서는 이처럼 null이 가능한 타입을 완전히 다르게 취급한다. 일례로 아래의 코드를 보자.
1
2
3
fun startsWithA(str: String): Boolean {
return str.startsWith("A")
}
- null 값이 들어갈 수 없는 타입이므로 바로 startsWith 메서드를 반환해도 에러가 발생하지 않는다.
- null이 들어갈 수 있는 타입으로 만든다면 조건으로 필터링하지 않을 경우 에러가 발생하게 된다.
null이 가능한 타입만을 위한 기능 (Safe Call, Elvis 연산자)
- Safe Call
1
2
3
val str: String? = "ABC"
str.length // (X)
str?.length // (O)
위 코드에서는 null이 들어갈 수 있는 타입이므로 length를 바로 호출할 수 없다.
?.을 사용하게 되면 호출이 가능해진다.
null이 아니면 실행하고, null이면 실행하지 않는다. 값이 null일 경우 결과로 null 그대로를 반환한다.
- Elvis 연산자
1
2
val str: String? = "ABC"
str?.length ?: 0
?:을 사용하며 앞의 연산 결과가 null이면 뒤의 값을 사용한다.
즉 str이 null이어서 str?.length의 결과가 null일 경우 0을 반환한다.
startsWith 메서드 수정
Elvis 연산자를 이용하여 조건문 없이 아래와 같이 수정 가능하다.
다른 예시들도 수정 가능하다.
1
2
3
4
fun startsWithA(str: String?): Boolean {
return str?.startsWith("A")
?: throw IllegalArgumentException("null");
}
null이 아님을 단언할 때
nullable 타입이지만, 아무리 생각해도 null이 될 수 없는 경우 명시적으로 선언할 수 있다.
1
2
3
fun startsWithA(str: String?): Boolean {
return str!!.startsWith("A")
}
!!를 통해 null이 아님을 단언할 수 있다.
- 혹시나 null이 들어갈 경우 NPE가 발생하기 때문에 null이 확실하게 들어오지 않는다고 확신이 들 경우에만 사용하자.
플랫폼 타입
kotlin에서 Java 코드를 가져다 사용할 때 어떻게 처리될까?
1
2
3
4
5
6
7
8
9
10
11
12
public class Person {
private final String name;
public Person(String name) {
this.name = name;
}
@Nullable
public String getName() {
return name;
}
}
1
2
3
4
5
6
7
8
9
10
11
fun main() {
val person = Person("lee")
startsWithA(person.name)
(자바 코드에서 @Nullable일 경우 X)
(@NotNull일 경우 O)
}
fun startsWithA(str: String): Boolean {
return str.startsWith("A")
//str: String?이 아니므로 NotNull인데 자바에서는 Nullable일 경우 에러
}
즉 코틀린에서는 자바 코드를 가져다 써도 자바의 애노테이션 정보를 이해할 수 있다.
- javax.annotation
- android.support.annotation
- org.jetbrains.nnotation
위 패키지들을 이해할 수 있다.
정리
- 코틀린에서 null이 들어갈 수 있는 타입은 완전히 다르게 간주된다.
- 한 번 null 검사를 하면 non-null임을 컴파일러가 알 수 있다.
- null이 아닌 경우에만 호출되는 Safe call (?.) 이 있다.
- null인 경우에만 호출되는 Elvis 연산자 (?:) 가 있다.
- null이 절대 아닐 때 사용하는 널 아님 단언 (!!) 이 있다.
- Kotlin에서 Java 코드를 사용할 때 플랫폼 타입 사용에 유의해야 한다.
- Java 코드에서 null 가능성을 확인하고 Kotlin으로 wrapping 한다.