class One {
fun print() {
Log.d("null_safety", "can you call me?")
}
}
var one: One
if(1 > 2) {
one = One()
}
one.print()
위 코드에서 1>2가 false기 때문에 one 변수는 아무것도 없는 null 상태가 된다. 이때 print 메서드를 호출하면 null 포인터 예외가 발생한다. 프로그램이나 앱이 작동을 멈출 수 있다는 얘기다.
그래서 코틀린은 이런 상황을 방지하기 위해 안전장치를 만들었는데 그것이 Null Safety이다.
코틀린에서 지정하는 기본 변수는 모두 null이 입력되지 않는다.
null값을 입력하기 위해서는 변수를 선언할 때 타입 뒤에 ?(Nullable, 물음표) 를 입력한다.
var variable: String?
var nullable: String? // 타입 다음에 물음표를 붙여서 null 값을 입력할 수 있다.
nullable = null
var notNullable: String
notNullable = null // 일반 변수에는 null 입력 불가
fun nullParameter(str: String?) { // 파라미터 str에 null이 허용되었기 때문에 함수 내부에서 null 체크를 하기 전에는 str을 사용할 수 없다.
if (str != null) {
var length2 = str.length
}
}
위 코드에서처럼 str 파라미터를 조건문 if에서 null인지 아닌지 체크해야지만 파라미터를 사용할 수 있다.
fun nullReturn(): String? {
return null
}
함수의 리턴 타입에도 물음표를 붙여 null 허용 여부를 설정할 수 있다.
?. 를 통해 null 체크를 좀 더 간결하게 할 수 있다.
Nullable인 변수 다음에 ?.을 사용하면 해당 변수가 null일 경우 ?. 다음의 메서드나 프로퍼티를 호출하지 않는다.
(앱이나 프로그램에서 null 값이 그대로 서비스 되어 버리면 안되는 상황에서 주로 사용)
fun testSafeCall(str: String?): Int? {
// str이 null이면 length를 체크하지 않고 null을 반환한다.
var resultNull: Int? = str?.length
return resultNull;
}
이번엔 엘비스 연산자(?:) 를 사용해서 원본 변수가 null일 때 넘겨줄 기본값을 설정해보자.
fun testElvis(str: String?): Int { // null 일때 0을 반환하기 때문에 리턴타입은 null 체크를 하지 않은 모습
// length 오른쪽에 ?:을 사용하면 null일 경우 ?: 오른쪽의 값이 반환된다.
var resultNonNull: Int = str?.length?:0
return resultNonNull;
}
표기법 : 선언하는 변수의 타입 다음에 ? 표기
사용 목적 : null을 입력받기 위해 사용
사용 예 : var nullable: 타입?
표기법 : 선언된 변수의 이름 다음에 ?. 표기
사용 목적 : null일 때 ?. 다음에 나오는 속성이나 명령어를 처리하지 않기 위해 사용
사용 예 : var result = 변수?.length 또는 변수?.프로퍼티?.something
표기법 : 선언된 변수의 이름 다음에 ?: 표기
사용 목적 : null일 때 ?: 다음에 나오는 값을 기본값으로 사용하기 위해
사용 예 : var result = 변수?:0 또는 변수?.프로퍼티?:0