23.01.13 Kotlin not null operator !!.
null과 자료형을 처리할 때 JAVA에서는 if 등의 조건문이나, error handling으로 이를 잡아주었다(자료형이 맞지 않는 경우에도 )
코틀린에서는 이를 간단하게 null operator를 통해 해결하였다.
https://kotlinlang.org/docs/null-safety.html
위의 문서는 kotlin의 null safety에 관한 공식문서이다.
아래와 같은 kotlin코드가 있다고 해보자. 보통 a라는 variable에 readLine으로 값을 사용자가 입력할 수 있는 형태이다.
이때 만약에 readLine에 해당하는 구문에 사용자가 null 값을 준다면? 에러가 발생할 것이다(toInt()로 바꿀수 없기에)
fun main(args: Array<String>) {
var a = readLine()!!.toInt()
var b = readLine()!!.toInt()
println(a+b)
}
이런 null인 경우들을 해결하기 위해 kotlin에서는 다양한 방법을 사용 가능하다.
!! : null이 아님을 보증한다
null 값이 아닐 것임을 보장한다. 라는 의미이다. 이를 not-null assertion 연산자라고 한다. 개발자가 논리적으로 절대 null이 발생하지 않을 것이니 안심해라, 라고 프로그램에 얘기한다고 생각하면 된다.
문제는 실제로 null이 발생하면 런타임상에서 에러가 발생한다는 것이 있다.
그러면 왜 사용할까? 가독성이 좋기 때문이다. 그럼 런타임 에러를 막을 수 있는 방법은 없을까?
? : make nullable
null이 가능하게 한다. 즉 nullable한 type으로 바꾸어준다.
fun main() {
val nullableString: String? = null
val nonNullString: String = "Hello World"
// val nonNullString: String = null 은 에러가 발생
}
?. :safe call operator
null이 아니면 해당값을 반환하고, 아니면 null을 반환해라라는 의미이다.
val a = "Kotlin"
val b: String? = null
println(b?.length)
println(a?.length) // Unnecessary safe call
즉 위의 경우에 b의 경우 null을 반환해준다.
?: :elvis operator
왼쪽에 해당하는 값이 null일 때 해당값을 default로 사용하고, 아니면 입력된 값을 써라라는 연산자이다.
fun main(args: Array<String>) {
var a = readLine()?.toIntOrNull() ?: 42
var b = readLine()?.toIntOrNull() ?: 42
println(a+b)
}
첫번째 case를 조금 변형한 것이다. 이 경우 a,b에 null인지 아닌지 확인하고, null이 아닌 경우 IntOrNull로 기능은 같고 다만 숫자로 바꿀수 없는건 null을 반환한다. 이 경우 ?:에 의해서 42를 값으로 반환한다.
as? : Safe cast operator
객체가 대상 타입이 아닌 경우 일반 캐스트로 인해 ClassCastException이 발생할 수 있다. 시도가 성공하지 못한 경우 null을 리턴하는 safe cast를 사용하여 runtime Error를 막는다.
fun main(args: Array<String>) {
var a: Int? = readLine() as? Int ?: 42
var b = readLine()?.toIntOrNull() ?: 42
println(a+b)
}
추가: getOrNull
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/get-or-null.html
getOrNull - Kotlin Programming Language
kotlinlang.org
array나 list에서 outOfRange에러가 일어날때 쓰기 좋은 함수.
fun main(args: Array<String>) {
val names = arrayOf("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
var day = readLine()?.toIntOrNull()?:100
var name = names.getOrNull(day)?:"Invalid day"
println(name)
}