?
를 붙여 명시적으로 null이 가능함을 표기해야 한다. val str: String = null // 컴파일 에러
val str: String? = null // 가능
// 함수 return type로도 가능.
fun parseInt(str: String): Int? {
// ...
}
그러나 null의 assign을 의도적으로 막은 것을 해제하였으니, 이러한 nullable variables는 NullPointerException
을 주의해야 한다.
val a: String? = "abc"
a = null
val len = a.length // error: variable "a" can be null
// 그래서 가장 간단하게는, condition으로 제어할 수 있다.
// 아래와 같은 경우, 컴파일러가 null의 가능성이 없음을 이해하고, 에러로 처리하지 않는다.
val len = if (a != null) a.length else -1
위와 같이 condition을 통해 명시하지 않더라도, null이 아닐 때에만 이하 method를 실행하라는 요구를 할 수 있다.
// return b.length if b is not null, and null otherwise.
// 그래서 자동적으로 len의 type는 Int?이다.
val len = a?.length
val bossName = bob?.department?.head?.name // 이렇게 chain이 있을 때에도 사용할 수 있다.
val a = "abc"
println(a?.length) // 이건 필요 없는 safe call이다.
그리고 nullable variable에, null이 아닐 때에만 특정 operation을 실행하려면, let
을 사용하면 된다.
val listWithNull: List<String?> = listOf("Kotlin", null)
for (item in listWithNull) {
item?.let {
prinln(it)
} // let 이하의 block은 item이 null이 아닐 때에만 실행
}
/// kotlin이 한 번만 출력된다.
nullable reference가 있을 때(a라 하자), "a가 null이 아닐 때에만 a를 쓰고, 아니면 다른 값을 쓰자"라는 코드를 작성하려면 ?:
를 쓸 수 있다. 이를 Elvis operator라 한다.
throw와 return도 kotlin에서는 expression이기 때문에, elvis operator의 RHS에 사용될 수 있다.
val l: Int = if (a != null) a.length else -1
// 동일한 표현이다
val l = a?.length ?: -1 // b?.length가 null이 아니라면 b.length를, null이라면 -1을 assign
fun foo(node: Node): String? {
val parent = node.getParent() ?: return null
val name = node.getName() ?: throw IllegalArgumentException("name expected")
// ...
}
이는 NPE를 발생시키기 위한 operator이다.
!!
는 컴파일 가능하게 두고 NPE를 발생시킬 수 있게 한다는 의미이다.val l = b!!.length // null 아니라면 b.length, null이라면 NPE 발생
Regular casts는 객체가 target type이 아닐 경우, ClassCastException을 발생시킬 수 있다.
이때 as?
를 사용하면 만약 다른 type을 casting하게 된다고 하더라도, 런타임 에러를 발생시키는 대신 null을 넣어 넘어가 준다.
val aInt: Int? = x as? Int // casting 실패시에도 null로 초기화 (expection이 발생하지 않음)
non-null elements만 필터링하고 싶은 경우, filterNoNull()
을 사용할 수 있다.
val nullableList: List<Int?> = listOf(1, 2, null)
val intList: List<Int> = nullableList.filterNoNull()
// 1, 2만 담긴다.